diff --git a/.github/workflows/build_one_target.yml b/.github/workflows/build_one_target.yml index 706b9cfe7..806df4e7a 100644 --- a/.github/workflows/build_one_target.yml +++ b/.github/workflows/build_one_target.yml @@ -4,9 +4,14 @@ on: workflow_dispatch: inputs: # trunk-ignore(checkov/CKV_GHA_7) + target: + type: string + required: false + description: Choose the target board, e.g. nrf52_promicro_diy_tcxo. If blank, will find available targets. arch: type: choice options: + - all - esp32 - esp32s3 - esp32c3 @@ -15,32 +20,18 @@ on: - rp2040 - rp2350 - stm32 - target: - type: string - required: false - description: Choose the target board, e.g. nrf52_promicro_diy_tcxo. If blank, will find available targets. - # find-target: - # type: boolean - # default: true - # description: 'Find the available targets' + description: Choose an arch to limit the search, or 'all' to search all architectures. + default: all permissions: read-all jobs: find-targets: - if: ${{ inputs.target == '' }} strategy: fail-fast: false matrix: arch: - - esp32 - - esp32s3 - - esp32c3 - - esp32c6 - - nrf52840 - - rp2040 - - rp2350 - - stm32 + - all runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 @@ -51,14 +42,37 @@ jobs: - run: pip install -U platformio - name: Generate matrix id: jsonStep + env: + BUILDTARGET: ${{ inputs.target }} + MATRIXARCH: ${{ inputs.arch }} run: | TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} --level extra) - echo "Name: $GITHUB_REF_NAME" >> $GITHUB_STEP_SUMMARY - echo "Base: $GITHUB_BASE_REF" >> $GITHUB_STEP_SUMMARY - echo "Arch: ${{matrix.arch}}" >> $GITHUB_STEP_SUMMARY - echo "Ref: $GITHUB_REF" >> $GITHUB_STEP_SUMMARY - echo "Targets:" >> $GITHUB_STEP_SUMMARY - echo $TARGETS | jq -r 'sort_by(.board) |.[] | "- " + .board' >> $GITHUB_STEP_SUMMARY + if [ "$BUILDTARGET" = "" ]; then + echo "Name: $GITHUB_REF_NAME" >> $GITHUB_STEP_SUMMARY + echo "Base: $GITHUB_BASE_REF" >> $GITHUB_STEP_SUMMARY + echo "Arch: $MATRIXARCH" >> $GITHUB_STEP_SUMMARY + echo "Ref: $GITHUB_REF" >> $GITHUB_STEP_SUMMARY + echo "## 🎯 The following target boards are available to build:" >> $GITHUB_STEP_SUMMARY + echo "| Platform | Board |" >> $GITHUB_STEP_SUMMARY + echo "| -------- | ----- |" >> $GITHUB_STEP_SUMMARY + echo $TARGETS | jq -r 'sort_by(.board) | sort_by(.platform) |.[] | "| " + .platform + " | " + .board + " |" ' >> $GITHUB_STEP_SUMMARY + else + echo "We build this one:" >> $GITHUB_STEP_SUMMARY + ARCH=$(echo "$TARGETS" | jq --arg BUILDTARGET "$BUILDTARGET" -r '.[] | select(.board==$BUILDTARGET) | .platform') + echo "| Platform | Board |" >> $GITHUB_STEP_SUMMARY + echo "| -------- | ----- |" >> $GITHUB_STEP_SUMMARY + echo "| $ARCH | "$BUILDTARGET" |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [[ "$ARCH" == "" ]]; then + echo "## ❌ Error: Target "$BUILDTARGET" not found!" >> $GITHUB_STEP_SUMMARY + else + echo "## ✅ Target "$BUILDTARGET" found, proceeding to build." >> $GITHUB_STEP_SUMMARY + fi + echo "You may need to refresh this page to make the built firmware appear below." >> $GITHUB_STEP_SUMMARY + echo "arch=$ARCH" >> $GITHUB_OUTPUT + fi + outputs: + arch: ${{ steps.jsonStep.outputs.arch }} version: if: ${{ inputs.target != '' }} @@ -78,12 +92,12 @@ jobs: build: if: ${{ inputs.target != '' && inputs.arch != 'native' }} - needs: [version] + needs: [version, find-targets] uses: ./.github/workflows/build_firmware.yml with: version: ${{ needs.version.outputs.long }} pio_env: ${{ inputs.target }} - platform: ${{ inputs.arch }} + platform: ${{ needs.find-targets.outputs.arch }} gather-artifacts: permissions: diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 5ecc0aeba..05f1bb22e 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,20 +8,20 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - checkov@3.2.511 - - renovate@43.92.1 + - checkov@3.2.513 + - renovate@43.104.6 - prettier@3.8.1 - - trufflehog@3.94.1 + - trufflehog@3.94.2 - yamllint@1.38.0 - bandit@1.9.4 - trivy@0.69.3 - taplo@0.10.0 - - ruff@0.15.8 + - ruff@0.15.9 - isort@8.0.1 - markdownlint@0.48.0 - oxipng@10.1.0 - svgo@4.0.1 - - actionlint@1.7.11 + - actionlint@1.7.12 - flake8@7.3.0 - hadolint@2.14.0 - shfmt@3.6.0 diff --git a/bin/config.d/femtofox/femtofox_E80-900M2213S.yaml b/bin/config.d/femtofox/femtofox_E80-900M2213S.yaml new file mode 100644 index 000000000..2f2b24603 --- /dev/null +++ b/bin/config.d/femtofox/femtofox_E80-900M2213S.yaml @@ -0,0 +1,30 @@ +--- +Lora: +## Ebyte E80-900M22S +## This is a bit experimental +## +## + Module: lr1121 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO3_TCXO_VOLTAGE: 1.8 + CS: 16 #pin6 / GPIO48 1C0 + IRQ: 23 #pin17 / GPIO55 1C7 + Busy: 22 #pin16 / GPIO54 1C6 + Reset: 25 #pin13 / GPIO57 1D1 + + + spidev: spidev0.0 #pins are (CS=16, CLK=17, MOSI=18, MISO=19) + spiSpeed: 2000000 + +rfswitch_table: + pins: [DIO5, DIO6, DIO7] + MODE_STBY: [LOW, LOW, LOW] + MODE_RX: [LOW, HIGH, LOW] + MODE_TX: [HIGH, HIGH, LOW] + MODE_TX_HP: [HIGH, LOW, LOW] + MODE_TX_HF: [LOW, LOW, LOW] + MODE_GNSS: [LOW, LOW, HIGH] + MODE_WIFI: [LOW, LOW, LOW] + +General: + MACAddressSource: eth0 diff --git a/bin/config.d/femtofox/femtofox_LR1121 generic.yaml b/bin/config.d/femtofox/femtofox_LR1121 generic.yaml new file mode 100644 index 000000000..c66eebed5 --- /dev/null +++ b/bin/config.d/femtofox/femtofox_LR1121 generic.yaml @@ -0,0 +1,46 @@ +--- +Lora: +## Ebyte E80-900M22S +## This is a bit experimental +## +## + Module: lr1121 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO3_TCXO_VOLTAGE: 1.8 + CS: 16 #pin6 / GPIO48 1C0 + IRQ: 23 #pin17 / GPIO55 1C7 + Busy: 22 #pin16 / GPIO54 1C6 + Reset: 25 #pin13 / GPIO57 1D1 + + + spidev: spidev0.0 #pins are (CS=16, CLK=17, MOSI=18, MISO=19) + spiSpeed: 2000000 + +rfswitch_table: + pins: + - DIO5 + - DIO6 + MODE_STBY: + - LOW + - LOW + MODE_RX: + - HIGH + - LOW + MODE_TX: + - HIGH + - HIGH + MODE_TX_HP: + - LOW + - HIGH + MODE_TX_HF: + - LOW + - LOW + MODE_GNSS: + - LOW + - LOW + MODE_WIFI: + - LOW + - LOW + +General: + MACAddressSource: eth0 diff --git a/bin/config.d/femtofox/femtofox_WIO-LR1121.yaml b/bin/config.d/femtofox/femtofox_WIO-LR1121.yaml new file mode 100644 index 000000000..c2ab76d46 --- /dev/null +++ b/bin/config.d/femtofox/femtofox_WIO-LR1121.yaml @@ -0,0 +1,30 @@ +--- +Lora: +## Ebyte E80-900M22S +## This is a bit experimental +## +## + Module: lr1121 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO3_TCXO_VOLTAGE: 1.8 + CS: 16 #pin6 / GPIO48 1C0 + IRQ: 23 #pin17 / GPIO55 1C7 + Busy: 22 #pin16 / GPIO54 1C6 + Reset: 25 #pin13 / GPIO57 1D1 + + + spidev: spidev0.0 #pins are (CS=16, CLK=17, MOSI=18, MISO=19) + spiSpeed: 2000000 + +rfswitch_table: + pins: [DIO5, DIO6, DIO7] + MODE_STBY: [LOW, LOW, LOW] + MODE_RX: [LOW, LOW, LOW] + MODE_TX: [LOW, HIGH, LOW] + MODE_TX_HP: [HIGH, LOW, LOW] + # MODE_TX_HF: [] + # MODE_GNSS: [] + MODE_WIFI: [LOW, LOW, LOW] + +General: + MACAddressSource: eth0 diff --git a/bin/config.d/lora-lyra-zero-MeshAdv-900M30S.yaml b/bin/config.d/lora-lyra-zero-MeshAdv-900M30S.yaml new file mode 100644 index 000000000..ea22c7953 --- /dev/null +++ b/bin/config.d/lora-lyra-zero-MeshAdv-900M30S.yaml @@ -0,0 +1,39 @@ +# MeshAdv-Pi E22-900M30S +# https://github.com/chrismyers2000/MeshAdv-Pi-Hat +Meta: + name: MeshAdv-Pi E22-900M30S + support: community + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 + CS: # GPIO0_C2 (physical 40) + pin: 18 + gpiochip: 0 + line: 18 + IRQ: # GPIO1_D1 (physical 36) + pin: 57 + gpiochip: 1 + line: 25 + Busy: # GPIO0_C1 (physical 38) + pin: 17 + gpiochip: 0 + line: 17 + Reset: # GPIO0_B6 (physical 12) + pin: 14 + gpiochip: 0 + line: 14 + TXen: # GPIO1_C2 (physical 33) + pin: 50 + gpiochip: 1 + line: 18 + RXen: # GPIO1_D2 (physical 32) + pin: 58 + gpiochip: 1 + line: 26 + DIO3_TCXO_VOLTAGE: true + # Only for E22-900M33S: + # Limit the output power to 8 dBm + # SX126X_MAX_POWER: 8 + spidev: spidev0.0 diff --git a/bin/config.d/lora-lyra-zero-MeshAdv-Mini-900M22S.yaml b/bin/config.d/lora-lyra-zero-MeshAdv-Mini-900M22S.yaml new file mode 100644 index 000000000..1fb150b15 --- /dev/null +++ b/bin/config.d/lora-lyra-zero-MeshAdv-Mini-900M22S.yaml @@ -0,0 +1,33 @@ +# MeshAdv Mini E22-900M22S +# https://github.com/chrismyers2000/MeshAdv-Mini +Meta: + name: MeshAdv Mini E22-900M22S + support: community + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 # Ebyte E22-900M22S + CS: # GPIO0_B2_d (phys 24, RPi CE0) + pin: 10 + gpiochip: 0 + line: 10 + IRQ: # GPIO1_D1_d (phys 36, RPi GPIO16) + pin: 57 + gpiochip: 1 + line: 25 + Busy: # GPIO0_C1_d (phys 38, RPi GPIO20) + pin: 17 + gpiochip: 0 + line: 17 + Reset: # GPIO0_B4_d (phys 18, RPi GPIO24) + pin: 12 + gpiochip: 0 + line: 12 + RXen: # GPIO1_D2_d (phys 32, RPi GPIO12) + pin: 58 + gpiochip: 1 + line: 26 + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + spidev: spidev0.0 diff --git a/bin/config.d/lora-lyra-zero-RAK6421-13300-slot1.yaml b/bin/config.d/lora-lyra-zero-RAK6421-13300-slot1.yaml new file mode 100644 index 000000000..b65a30c20 --- /dev/null +++ b/bin/config.d/lora-lyra-zero-RAK6421-13300-slot1.yaml @@ -0,0 +1,38 @@ +Meta: + name: RAK6421 + RAK13300 Slot 1 + support: community # Promote when tested + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_A5 (IO6) + pin: 5 + gpiochip: 0 + line: 5 + Reset: # GPIO1_D1 (IO4) + pin: 57 + gpiochip: 1 + line: 25 + Busy: # GPIO0_B4 (IO5) + pin: 12 + gpiochip: 0 + line: 12 + # Ant_sw: # GPIO1_C2 (IO3) + # pin: 50 + # gpiochip: 1 + # line: 18 + Enable_Pins: + - pin: 58 # GPIO1_D2 + gpiochip: 1 + line: 26 + - pin: 50 # GPIO1_C2 + gpiochip: 1 + line: 18 + DIO3_TCXO_VOLTAGE: true + DIO2_AS_RF_SWITCH: true + spidev: spidev0.0 + # CS: # GPIO0_B2 + # pin: 10 + # gpiochip: 0 + # line: 10 diff --git a/bin/config.d/lora-lyra-zero-RAK6421-13300-slot2.yaml b/bin/config.d/lora-lyra-zero-RAK6421-13300-slot2.yaml new file mode 100644 index 000000000..255a3eca3 --- /dev/null +++ b/bin/config.d/lora-lyra-zero-RAK6421-13300-slot2.yaml @@ -0,0 +1,36 @@ +Meta: + name: RAK6421 + RAK13300 Slot 2 + support: community # Promote when tested + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_B6 (IO6) + pin: 14 + gpiochip: 0 + line: 14 + Reset: # GPIO0_B4 (IO4) + pin: 12 + gpiochip: 0 + line: 12 + Busy: # GPIO1_C0 (IO5) + pin: 48 + gpiochip: 1 + line: 16 + # Ant_sw: # GPIO0_B5 (IO3) + # pin: 13 + # gpiochip: 0 + # line: 13 + Enable_Pins: + - pin: 51 # GPIO1_C3 + gpiochip: 1 + line: 19 + - pin: 13 # GPIO0_B5 + gpiochip: 0 + line: 13 + spidev: spidev0.1 + # CS: # GPIO0_B1 + # pin: 9 + # gpiochip: 0 + # line: 9 diff --git a/bin/config.d/lora-lyra-zero-RAK6421-13302-slot1.yaml b/bin/config.d/lora-lyra-zero-RAK6421-13302-slot1.yaml new file mode 100644 index 000000000..c37c6fb3a --- /dev/null +++ b/bin/config.d/lora-lyra-zero-RAK6421-13302-slot1.yaml @@ -0,0 +1,39 @@ +Meta: + name: RAK6421 + RAK13300 Slot 1 + support: community # Promote when tested + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_A5 (IO6) + pin: 5 + gpiochip: 0 + line: 5 + Reset: # GPIO1_D1 (IO4) + pin: 57 + gpiochip: 1 + line: 25 + Busy: # GPIO0_B4 (IO5) + pin: 12 + gpiochip: 0 + line: 12 + # Ant_sw: # GPIO1_C2 (IO3) + # pin: 50 + # gpiochip: 1 + # line: 18 + Enable_Pins: + - pin: 58 # GPIO1_D2 + gpiochip: 1 + line: 26 + - pin: 50 # GPIO1_C2 + gpiochip: 1 + line: 18 + DIO3_TCXO_VOLTAGE: true + DIO2_AS_RF_SWITCH: true + spidev: spidev0.0 + # CS: # GPIO0_B2 + # pin: 10 + # gpiochip: 0 + # line: 10 + TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8] diff --git a/bin/config.d/lora-lyra-zero-RAK6421-13302-slot2.yaml b/bin/config.d/lora-lyra-zero-RAK6421-13302-slot2.yaml new file mode 100644 index 000000000..773a35ab0 --- /dev/null +++ b/bin/config.d/lora-lyra-zero-RAK6421-13302-slot2.yaml @@ -0,0 +1,37 @@ +Meta: + name: RAK6421 + RAK13300 Slot 2 + support: community # Promote when tested + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 + IRQ: # GPIO0_B6 (IO6) + pin: 14 + gpiochip: 0 + line: 14 + Reset: # GPIO0_B4 (IO4) + pin: 12 + gpiochip: 0 + line: 12 + Busy: # GPIO1_C0 (IO5) + pin: 48 + gpiochip: 1 + line: 16 + # Ant_sw: # GPIO0_B5 (IO3) + # pin: 13 + # gpiochip: 0 + # line: 13 + Enable_Pins: + - pin: 51 # GPIO1_C3 + gpiochip: 1 + line: 19 + - pin: 13 # GPIO0_B5 + gpiochip: 0 + line: 13 + spidev: spidev0.1 + # CS: # GPIO0_B1 + # pin: 9 + # gpiochip: 0 + # line: 9 + TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8] diff --git a/bin/config.d/lora-lyra-zero-waveshare-sxxx.yaml b/bin/config.d/lora-lyra-zero-waveshare-sxxx.yaml new file mode 100644 index 000000000..934945202 --- /dev/null +++ b/bin/config.d/lora-lyra-zero-waveshare-sxxx.yaml @@ -0,0 +1,30 @@ +Meta: + name: Waveshare SX1262 + support: deprecated + compatible: + - luckfox-lyra-zero-w # Armbian + +Lora: + Module: sx1262 # Waveshare SX126X XXXM + DIO2_AS_RF_SWITCH: true + CS: # GPIO0_C2 (physical 40) + pin: 18 + gpiochip: 0 + line: 18 + IRQ: # GPIO1_D1 (physical 36) + pin: 57 + gpiochip: 1 + line: 25 + Busy: # GPIO0_C1 (physical 38) + pin: 17 + gpiochip: 0 + line: 17 + Reset: # GPIO0_B6 (physical 12) + pin: 14 + gpiochip: 0 + line: 14 + SX126X_ANT_SW: # GPIO1_B3 (physical 31) + pin: 43 + gpiochip: 1 + line: 11 + spidev: spidev0.0 diff --git a/bin/generate_ci_matrix.py b/bin/generate_ci_matrix.py index b4c18c05b..1458e4390 100755 --- a/bin/generate_ci_matrix.py +++ b/bin/generate_ci_matrix.py @@ -43,7 +43,7 @@ for pio_env in pio_envs: env = { "ci": {"board": 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)), + "board_check": cfg.get(f"env:{pio_env}", "board_check", default="false").strip().lower() == "true", } all_envs.append(env) diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index fe3a3a533..0642fdb07 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.22 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.21 diff --git a/boards/ttgo-tbeam.json b/boards/ttgo-tbeam.json new file mode 100644 index 000000000..a4c43d525 --- /dev/null +++ b/boards/ttgo-tbeam.json @@ -0,0 +1,29 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_T_Beam", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "tbeam" + }, + "connectivity": ["wifi", "bluetooth", "can", "ethernet"], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "TTGO T-Beam (PSRAM Disabled)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/LilyGO/TTGO-T-Beam", + "vendor": "TTGO" +} diff --git a/debian/changelog b/debian/changelog index 13d751ecf..b13a2ae9d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +meshtasticd (2.7.22.0) unstable; urgency=medium + + * Version 2.7.22 + + -- GitHub Actions Mon, 06 Apr 2026 11:34:12 +0000 + meshtasticd (2.7.21.0) unstable; urgency=medium * Version 2.7.21 diff --git a/platformio.ini b/platformio.ini index 45d59942d..83a5a7057 100644 --- a/platformio.ini +++ b/platformio.ini @@ -126,7 +126,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/7b1485b86c8d55a40e5226749097767e8b87f396.zip + https://github.com/meshtastic/device-ui/archive/1897dd17fceb1f101bb1a3245680aa3439edcfdd.zip ; Common libs for environmental measurements in telemetry module [environmental_base] @@ -195,16 +195,10 @@ lib_deps = adafruit/Adafruit BMP3XX Library@2.1.6 # renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X adafruit/Adafruit MAX1704X@1.0.3 - # renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library - adafruit/Adafruit SHTC3 Library@1.0.2 # renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X adafruit/Adafruit LPS2X@2.0.6 - # renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library - adafruit/Adafruit SHT31 Library@2.2.2 # renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library adafruit/Adafruit VEML7700 Library@2.1.6 - # renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library - adafruit/Adafruit SHT4x Library@1.0.5 # renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6 # renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001 @@ -219,6 +213,8 @@ lib_deps = sensirion/Sensirion I2C SFA3x@1.0.0 # renovate: datasource=custom.pio depName=Sensirion I2C SCD30 packageName=sensirion/library/Sensirion I2C SCD30 sensirion/Sensirion I2C SCD30@1.0.0 + # renovate: datasource=custom.pio depName=arduino-sht packageName=sensirion/library/arduino-sht + sensirion/arduino-sht@1.2.6 ; Environmental sensors with BSEC2 (Bosch proprietary IAQ) [environmental_extra] diff --git a/protobufs b/protobufs index cb1f89372..e30092e61 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit cb1f89372a70b0d4b4f8caf05aec28de8d4a13e0 +Subproject commit e30092e6168b13341c2b7ec4be19c789ad5cd77f diff --git a/renovate.json b/renovate.json index d761f61c1..60c51b59e 100644 --- a/renovate.json +++ b/renovate.json @@ -4,6 +4,7 @@ ":dependencyDashboard", ":semanticCommitTypeAll(chore)", ":ignoreModulesAndTests", + ":noUnscheduledUpdates", "schedule:daily", "group:recommended", "replacements:all", diff --git a/src/configuration.h b/src/configuration.h index 11be86007..84dabee4e 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -231,7 +231,7 @@ along with this program. If not, see . #define BME_ADDR 0x76 #define BME_ADDR_ALTERNATE 0x77 #define MCP9808_ADDR 0x18 -#define INA_ADDR 0x40 +#define INA_ADDR 0x40 // same as SHT2X #define INA_ADDR_ALTERNATE 0x41 #define INA_ADDR_WAVESHARE_UPS 0x43 #define INA3221_ADDR 0x42 @@ -244,8 +244,8 @@ along with this program. If not, see . #define LPS22HB_ADDR 0x5C #define LPS22HB_ADDR_ALT 0x5D #define SFA30_ADDR 0x5D -#define SHT31_4x_ADDR 0x44 -#define SHT31_4x_ADDR_ALT 0x45 +#define SHTXX_ADDR 0x44 +#define SHTXX_ADDR_ALT 0x45 #define PMSA003I_ADDR 0x12 #define QMA6100P_ADDR 0x12 #define AHT10_ADDR 0x38 diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index cc83a8d7b..d451d3948 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -31,9 +31,6 @@ class ScanI2C INA3221, MAX17048, MCP9808, - SHT31, - SHT4X, - SHTC3, LPS22HB, QMC6310U, QMC6310N, @@ -94,7 +91,8 @@ class ScanI2C SFA30, CW2015, SCD30, - ADS1115 + ADS1115, + SHTXX } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 2e00c11ce..052b2245a 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -136,7 +136,9 @@ bool ScanI2CTwoWire::i2cCommandResponseLength(ScanI2C::DeviceAddress addr, uint1 return match; } -/// for SEN5X detection +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR +// FIXME Move to a separate file for detection of sensors that require more complex interactions? +// For SEN5X detection // Note, this code needs to be called before setting the I2C bus speed // for the screen at high speed. The speed needs to be at 100kHz, otherwise // detection will not work @@ -174,6 +176,46 @@ String readSEN5xProductName(TwoWire *i2cBus, uint8_t address) return String(productName); } +#endif + +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR +bool detectSHT21SerialNumber(TwoWire *i2cBus, uint8_t address) +{ + + i2cBus->beginTransmission(address); + i2cBus->write(0xFA); + i2cBus->write(0x0F); + + if (i2cBus->endTransmission() != 0) + return false; + + if (i2cBus->requestFrom(address, (uint8_t)8) != 8) + return false; + + // Just flush the data + while (i2cBus->available() < 8) { + i2cBus->read(); + } + + i2cBus->beginTransmission(address); + i2cBus->write(0xFC); + i2cBus->write(0xC9); + + if (i2cBus->endTransmission() != 0) + return false; + + if (i2cBus->requestFrom(address, (uint8_t)6) != 6) + return false; + + // Just flush the data + while (i2cBus->available() < 6) { + i2cBus->read(); + } + + // Assume we detect the SHT21 if something came back from the request + return true; +} +#endif #define SCAN_SIMPLE_CASE(ADDR, T, ...) \ case ADDR: \ @@ -371,7 +413,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) break; #endif #if !defined(M5STACK_UNITC6L) - case INA_ADDR: + case INA_ADDR: // Same as SHT2X case INA_ADDR_ALTERNATE: case INA_ADDR_WAVESHARE_UPS: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2); @@ -387,7 +429,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) logFoundDevice("INA260", (uint8_t)addr.address); type = INA260; } - } else { // Assume INA219 if INA260 ID is not found +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + } else if (detectSHT21SerialNumber(i2cBus, (uint8_t)addr.address)) { + logFoundDevice("SHTXX (SHT2X)", (uint8_t)addr.address); + type = SHTXX; +#endif + } else { // Assume INA219 if none of the above ones are found logFoundDevice("INA219", (uint8_t)addr.address); type = INA219; } @@ -448,22 +495,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) } break; } - case SHT31_4x_ADDR: // same as OPT3001_ADDR_ALT - case SHT31_4x_ADDR_ALT: // same as OPT3001_ADDR + case SHTXX_ADDR: // same as OPT3001_ADDR_ALT + case SHTXX_ADDR_ALT: // same as OPT3001_ADDR if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) { type = OPT3001; logFoundDevice("OPT3001", (uint8_t)addr.address); - } else if (i2cCommandResponseLength(addr, 0x89, 6)) { // SHT4x serial number (6 bytes inc. CRC) - type = SHT4X; - logFoundDevice("SHT4X", (uint8_t)addr.address); - } else { - type = SHT31; - logFoundDevice("SHT31", (uint8_t)addr.address); + } else { // SHTXX + type = SHTXX; + logFoundDevice("SHTXX", (uint8_t)addr.address); } break; - SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3", (uint8_t)addr.address) + SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTXX, "SHTXX", (uint8_t)addr.address) case RCWL9620_ADDR: // get MAX30102 PARTID registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1); @@ -675,6 +719,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) logFoundDevice("BMX160", (uint8_t)addr.address); break; } else { +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR String prod = ""; prod = readSEN5xProductName(i2cBus, addr.address); if (prod.startsWith("SEN55")) { @@ -690,6 +735,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) logFoundDevice("Sensirion SEN50", addr.address); break; } +#endif if (addr.address == BMX160_ADDR) { type = BMX160; logFoundDevice("BMX160", (uint8_t)addr.address); diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 005ead292..4c8272955 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -1254,14 +1254,14 @@ void TFTDisplay::display(bool fromBlank) // Did we find a pixel that needs updating on this row? if (x_FirstPixelUpdate < displayWidth) { + // Align the first pixel for update to an even number so the total alignment of + // the data will be at 32-bit boundary, which is required by GDMA SPI transfers. + x_FirstPixelUpdate &= ~1; - // Quickly write out the first changed pixel (saves another array lookup) - linePixelBuffer[x_FirstPixelUpdate] = isset ? colorTftMesh : colorTftBlack; - x_LastPixelUpdate = x_FirstPixelUpdate; - - // Step 3: copy all remaining pixels in this row into the pixel line buffer, - // while also recording the last pixel in the row that needs updating - for (x = x_FirstPixelUpdate + 1; x < displayWidth; x++) { + // Step 3a: copy rest of the pixels in this row into the pixel line buffer, + // while also recording the last pixel in the row that needs updating. + // Since the first changed pixel will be looked up, the x_LastPixelUpdate will be set. + for (x = x_FirstPixelUpdate; x < displayWidth; x++) { isset = buffer[x + y_byteIndex] & y_byteMask; linePixelBuffer[x] = isset ? colorTftMesh : colorTftBlack; @@ -1274,6 +1274,14 @@ void TFTDisplay::display(bool fromBlank) x_LastPixelUpdate = x; } } + // Step 3b: Round up the last pixel to odd number to maintain 32-bit alignment for SPIs. + // Most displays will have even number of pixels in a row -- this will be in bounds + // of the displayWidth. (Hopefully odd displays will just ignore that extra pixel.) + x_LastPixelUpdate |= 1; + // Ensure the last pixel index does not exceed the display width. + if (x_LastPixelUpdate >= displayWidth) { + x_LastPixelUpdate = displayWidth - 1; + } #if defined(HACKADAY_COMMUNICATOR) tft->draw16bitBeRGBBitmap(x_FirstPixelUpdate, y, &linePixelBuffer[x_FirstPixelUpdate], (x_LastPixelUpdate - x_FirstPixelUpdate + 1), 1); diff --git a/src/input/InputBroker.cpp b/src/input/InputBroker.cpp index e3125ca12..b7c9b27a9 100644 --- a/src/input/InputBroker.cpp +++ b/src/input/InputBroker.cpp @@ -299,6 +299,7 @@ void InputBroker::Init() // Buttons. Moved here cause we need NodeDB to be initialized // If your variant.h has a BUTTON_PIN defined, go ahead and define BUTTON_ACTIVE_LOW and BUTTON_ACTIVE_PULLUP UserButtonThread = new ButtonThread("UserButton"); +#if !MESHTASTIC_EXCLUDE_SCREEN if (screen) { ButtonConfig userConfig; userConfig.pinNumber = (uint8_t)_pinNum; @@ -317,7 +318,9 @@ void InputBroker::Init() userConfig.longPressTime = 500; userConfig.longLongPress = INPUT_BROKER_SHUTDOWN; UserButtonThread->initButton(userConfig); - } else { + } else +#endif + { ButtonConfig userConfigNoScreen; userConfigNoScreen.pinNumber = (uint8_t)_pinNum; userConfigNoScreen.activeLow = BUTTON_ACTIVE_LOW; @@ -379,11 +382,13 @@ void InputBroker::Init() } #endif // HAS_BUTTON #if ARCH_PORTDUINO - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR && portduino_config.i2cdev != "") { - seesawRotary = new SeesawRotary("SeesawRotary"); - if (!seesawRotary->init()) { - delete seesawRotary; - seesawRotary = nullptr; + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + if (portduino_config.i2cdev != "") { + seesawRotary = new SeesawRotary("SeesawRotary"); + if (!seesawRotary->init()) { + delete seesawRotary; + seesawRotary = nullptr; + } } aLinuxInputImpl = new LinuxInputImpl(); aLinuxInputImpl->init(); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 01be50c26..4b0871566 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -819,7 +819,7 @@ void NodeDB::installDefaultModuleConfig() moduleConfig.has_store_forward = true; moduleConfig.has_telemetry = true; moduleConfig.has_external_notification = true; -#if defined(PIN_BUZZER) || defined(PIN_VIBRATION) || defined(LED_NOTIFICATION) +#if defined(PIN_BUZZER) || defined(PIN_VIBRATION) || defined(LED_NOTIFICATION) || defined(PCA_LED_NOTIFICATION) moduleConfig.external_notification.enabled = true; #endif #if defined(PIN_BUZZER) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 9ce944002..19757b63c 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -152,8 +152,10 @@ const RegionInfo regions[] = { /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf + https://standard.nbtc.go.th/getattachment/Standards/%E0%B8%A1%E0%B8%B2%E0%B8%95%E0%B8%A3%E0%B8%90%E0%B8%B2%E0%B8%99%E0%B8%97%E0%B8%B2%E0%B8%87%E0%B9%80%E0%B8%97%E0%B8%84%E0%B8%99%E0%B8%B4%E0%B8%84%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%84%E0%B8%A3%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%82%E0%B8%97%E0%B8%A3%E0%B8%84%E0%B8%A1%E0%B8%99%E0%B8%B2%E0%B8%84%E0%B8%A1/1033-2565.pdf.aspx?lang=th-TH + Thailand 920–925 MHz set max TX power to 27 dBm and enforce 10% duty cycle, aligned with NBTC regulations. */ - RDEF(TH, 920.0f, 925.0f, 100, 16, false, false, PROFILE_STD), + RDEF(TH, 920.0f, 925.0f, 10, 27, false, false, PROFILE_STD), /* 433,05-434,7 Mhz 10 mW @@ -961,7 +963,7 @@ void RadioInterface::applyModemConfig() cr = loraConfig.coding_rate; LOG_INFO("Using custom Coding Rate %u", cr); } else { - cr = loraConfig.coding_rate; + cr = newcr; } } else { // if not using preset, then just use the custom settings diff --git a/src/mesh/generated/meshtastic/atak.pb.cpp b/src/mesh/generated/meshtastic/atak.pb.cpp index a0368cf6b..bbafa33e2 100644 --- a/src/mesh/generated/meshtastic/atak.pb.cpp +++ b/src/mesh/generated/meshtastic/atak.pb.cpp @@ -24,6 +24,18 @@ PB_BIND(meshtastic_Contact, meshtastic_Contact, AUTO) PB_BIND(meshtastic_PLI, meshtastic_PLI, AUTO) +PB_BIND(meshtastic_AircraftTrack, meshtastic_AircraftTrack, AUTO) + + +PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2) + + + + + + + + diff --git a/src/mesh/generated/meshtastic/atak.pb.h b/src/mesh/generated/meshtastic/atak.pb.h index 8533bcbf9..c12b042f4 100644 --- a/src/mesh/generated/meshtastic/atak.pb.h +++ b/src/mesh/generated/meshtastic/atak.pb.h @@ -65,6 +65,197 @@ typedef enum _meshtastic_MemberRole { meshtastic_MemberRole_K9 = 8 } meshtastic_MemberRole; +/* CoT how field values. + Represents how the coordinates were generated. */ +typedef enum _meshtastic_CotHow { + /* Unspecified */ + meshtastic_CotHow_CotHow_Unspecified = 0, + /* Human entered */ + meshtastic_CotHow_CotHow_h_e = 1, + /* Machine generated */ + meshtastic_CotHow_CotHow_m_g = 2, + /* Human GPS/INS derived */ + meshtastic_CotHow_CotHow_h_g_i_g_o = 3, + /* Machine relayed (imported from another system/gateway) */ + meshtastic_CotHow_CotHow_m_r = 4, + /* Machine fused (corroborated from multiple sources) */ + meshtastic_CotHow_CotHow_m_f = 5, + /* Machine predicted */ + meshtastic_CotHow_CotHow_m_p = 6, + /* Machine simulated */ + meshtastic_CotHow_CotHow_m_s = 7 +} meshtastic_CotHow; + +/* Well-known CoT event types. + When the type is known, use the enum value for efficient encoding. + For unknown types, set cot_type_id to CotType_Other and populate cot_type_str. */ +typedef enum _meshtastic_CotType { + /* Unknown or unmapped type, use cot_type_str */ + meshtastic_CotType_CotType_Other = 0, + /* a-f-G-U-C: Friendly ground unit combat */ + meshtastic_CotType_CotType_a_f_G_U_C = 1, + /* a-f-G-U-C-I: Friendly ground unit combat infantry */ + meshtastic_CotType_CotType_a_f_G_U_C_I = 2, + /* a-n-A-C-F: Neutral aircraft civilian fixed-wing */ + meshtastic_CotType_CotType_a_n_A_C_F = 3, + /* a-n-A-C-H: Neutral aircraft civilian helicopter */ + meshtastic_CotType_CotType_a_n_A_C_H = 4, + /* a-n-A-C: Neutral aircraft civilian */ + meshtastic_CotType_CotType_a_n_A_C = 5, + /* a-f-A-M-H: Friendly aircraft military helicopter */ + meshtastic_CotType_CotType_a_f_A_M_H = 6, + /* a-f-A-M: Friendly aircraft military */ + meshtastic_CotType_CotType_a_f_A_M = 7, + /* a-f-A-M-F-F: Friendly aircraft military fixed-wing fighter */ + meshtastic_CotType_CotType_a_f_A_M_F_F = 8, + /* a-f-A-M-H-A: Friendly aircraft military helicopter attack */ + meshtastic_CotType_CotType_a_f_A_M_H_A = 9, + /* a-f-A-M-H-U-M: Friendly aircraft military helicopter utility medium */ + meshtastic_CotType_CotType_a_f_A_M_H_U_M = 10, + /* a-h-A-M-F-F: Hostile aircraft military fixed-wing fighter */ + meshtastic_CotType_CotType_a_h_A_M_F_F = 11, + /* a-h-A-M-H-A: Hostile aircraft military helicopter attack */ + meshtastic_CotType_CotType_a_h_A_M_H_A = 12, + /* a-u-A-C: Unknown aircraft civilian */ + meshtastic_CotType_CotType_a_u_A_C = 13, + /* t-x-d-d: Tasking delete/disconnect */ + meshtastic_CotType_CotType_t_x_d_d = 14, + /* a-f-G-E-S-E: Friendly ground equipment sensor */ + meshtastic_CotType_CotType_a_f_G_E_S_E = 15, + /* a-f-G-E-V-C: Friendly ground equipment vehicle */ + meshtastic_CotType_CotType_a_f_G_E_V_C = 16, + /* a-f-S: Friendly sea */ + meshtastic_CotType_CotType_a_f_S = 17, + /* a-f-A-M-F: Friendly aircraft military fixed-wing */ + meshtastic_CotType_CotType_a_f_A_M_F = 18, + /* a-f-A-M-F-C-H: Friendly aircraft military fixed-wing cargo heavy */ + meshtastic_CotType_CotType_a_f_A_M_F_C_H = 19, + /* a-f-A-M-F-U-L: Friendly aircraft military fixed-wing utility light */ + meshtastic_CotType_CotType_a_f_A_M_F_U_L = 20, + /* a-f-A-M-F-L: Friendly aircraft military fixed-wing liaison */ + meshtastic_CotType_CotType_a_f_A_M_F_L = 21, + /* a-f-A-M-F-P: Friendly aircraft military fixed-wing patrol */ + meshtastic_CotType_CotType_a_f_A_M_F_P = 22, + /* a-f-A-C-H: Friendly aircraft civilian helicopter */ + meshtastic_CotType_CotType_a_f_A_C_H = 23, + /* a-n-A-M-F-Q: Neutral aircraft military fixed-wing drone */ + meshtastic_CotType_CotType_a_n_A_M_F_Q = 24, + /* b-t-f: GeoChat message */ + meshtastic_CotType_CotType_b_t_f = 25, + /* b-r-f-h-c: CASEVAC/MEDEVAC report */ + meshtastic_CotType_CotType_b_r_f_h_c = 26, + /* b-a-o-pan: Ring the bell / alert all */ + meshtastic_CotType_CotType_b_a_o_pan = 27, + /* b-a-o-opn: Troops in contact */ + meshtastic_CotType_CotType_b_a_o_opn = 28, + /* b-a-o-can: Cancel alert */ + meshtastic_CotType_CotType_b_a_o_can = 29, + /* b-a-o-tbl: 911 alert */ + meshtastic_CotType_CotType_b_a_o_tbl = 30, + /* b-a-g: Geofence breach alert */ + meshtastic_CotType_CotType_b_a_g = 31, + /* a-f-G: Friendly ground (generic) */ + meshtastic_CotType_CotType_a_f_G = 32, + /* a-f-G-U: Friendly ground unit (generic) */ + meshtastic_CotType_CotType_a_f_G_U = 33, + /* a-h-G: Hostile ground (generic) */ + meshtastic_CotType_CotType_a_h_G = 34, + /* a-u-G: Unknown ground (generic) */ + meshtastic_CotType_CotType_a_u_G = 35, + /* a-n-G: Neutral ground (generic) */ + meshtastic_CotType_CotType_a_n_G = 36, + /* b-m-r: Route */ + meshtastic_CotType_CotType_b_m_r = 37, + /* b-m-p-w: Route waypoint */ + meshtastic_CotType_CotType_b_m_p_w = 38, + /* b-m-p-s-p-i: Self-position marker */ + meshtastic_CotType_CotType_b_m_p_s_p_i = 39, + /* u-d-f: Freeform shape (line/polygon) */ + meshtastic_CotType_CotType_u_d_f = 40, + /* u-d-r: Rectangle */ + meshtastic_CotType_CotType_u_d_r = 41, + /* u-d-c-c: Circle */ + meshtastic_CotType_CotType_u_d_c_c = 42, + /* u-rb-a: Range/bearing line */ + meshtastic_CotType_CotType_u_rb_a = 43, + /* a-h-A: Hostile aircraft (generic) */ + meshtastic_CotType_CotType_a_h_A = 44, + /* a-u-A: Unknown aircraft (generic) */ + meshtastic_CotType_CotType_a_u_A = 45, + /* a-f-A-M-H-Q: Friendly aircraft military helicopter observation */ + meshtastic_CotType_CotType_a_f_A_M_H_Q = 46, + /* a-f-A-C-F: Friendly aircraft civilian fixed-wing */ + meshtastic_CotType_CotType_a_f_A_C_F = 47, + /* a-f-A-C: Friendly aircraft civilian (generic) */ + meshtastic_CotType_CotType_a_f_A_C = 48, + /* a-f-A-C-L: Friendly aircraft civilian lighter-than-air */ + meshtastic_CotType_CotType_a_f_A_C_L = 49, + /* a-f-A: Friendly aircraft (generic) */ + meshtastic_CotType_CotType_a_f_A = 50, + /* a-f-A-M-H-C: Friendly aircraft military helicopter cargo */ + meshtastic_CotType_CotType_a_f_A_M_H_C = 51, + /* a-n-A-M-F-F: Neutral aircraft military fixed-wing fighter */ + meshtastic_CotType_CotType_a_n_A_M_F_F = 52, + /* a-u-A-C-F: Unknown aircraft civilian fixed-wing */ + meshtastic_CotType_CotType_a_u_A_C_F = 53, + /* a-f-G-U-C-F-T-A: Friendly ground unit combat forces theater aviation */ + meshtastic_CotType_CotType_a_f_G_U_C_F_T_A = 54, + /* a-f-G-U-C-V-S: Friendly ground unit combat vehicle support */ + meshtastic_CotType_CotType_a_f_G_U_C_V_S = 55, + /* a-f-G-U-C-R-X: Friendly ground unit combat reconnaissance exploitation */ + meshtastic_CotType_CotType_a_f_G_U_C_R_X = 56, + /* a-f-G-U-C-I-Z: Friendly ground unit combat infantry mechanized */ + meshtastic_CotType_CotType_a_f_G_U_C_I_Z = 57, + /* a-f-G-U-C-E-C-W: Friendly ground unit combat engineer construction wheeled */ + meshtastic_CotType_CotType_a_f_G_U_C_E_C_W = 58, + /* a-f-G-U-C-I-L: Friendly ground unit combat infantry light */ + meshtastic_CotType_CotType_a_f_G_U_C_I_L = 59, + /* a-f-G-U-C-R-O: Friendly ground unit combat reconnaissance other */ + meshtastic_CotType_CotType_a_f_G_U_C_R_O = 60, + /* a-f-G-U-C-R-V: Friendly ground unit combat reconnaissance cavalry */ + meshtastic_CotType_CotType_a_f_G_U_C_R_V = 61, + /* a-f-G-U-H: Friendly ground unit headquarters */ + meshtastic_CotType_CotType_a_f_G_U_H = 62, + /* a-f-G-U-U-M-S-E: Friendly ground unit support medical surgical evacuation */ + meshtastic_CotType_CotType_a_f_G_U_U_M_S_E = 63, + /* a-f-G-U-S-M-C: Friendly ground unit support maintenance collection */ + meshtastic_CotType_CotType_a_f_G_U_S_M_C = 64, + /* a-f-G-E-S: Friendly ground equipment sensor (generic) */ + meshtastic_CotType_CotType_a_f_G_E_S = 65, + /* a-f-G-E: Friendly ground equipment (generic) */ + meshtastic_CotType_CotType_a_f_G_E = 66, + /* a-f-G-E-V-C-U: Friendly ground equipment vehicle utility */ + meshtastic_CotType_CotType_a_f_G_E_V_C_U = 67, + /* a-f-G-E-V-C-ps: Friendly ground equipment vehicle public safety */ + meshtastic_CotType_CotType_a_f_G_E_V_C_ps = 68, + /* a-u-G-E-V: Unknown ground equipment vehicle */ + meshtastic_CotType_CotType_a_u_G_E_V = 69, + /* a-f-S-N-N-R: Friendly sea surface non-naval rescue */ + meshtastic_CotType_CotType_a_f_S_N_N_R = 70, + /* a-f-F-B: Friendly force boundary */ + meshtastic_CotType_CotType_a_f_F_B = 71, + /* b-m-p-s-p-loc: Self-position location marker */ + meshtastic_CotType_CotType_b_m_p_s_p_loc = 72, + /* b-i-v: Imagery/video */ + meshtastic_CotType_CotType_b_i_v = 73, + /* b-f-t-r: File transfer request */ + meshtastic_CotType_CotType_b_f_t_r = 74, + /* b-f-t-a: File transfer acknowledgment */ + meshtastic_CotType_CotType_b_f_t_a = 75 +} meshtastic_CotType; + +/* Geopoint and altitude source */ +typedef enum _meshtastic_GeoPointSource { + /* Unspecified */ + meshtastic_GeoPointSource_GeoPointSource_Unspecified = 0, + /* GPS derived */ + meshtastic_GeoPointSource_GeoPointSource_GPS = 1, + /* User entered */ + meshtastic_GeoPointSource_GeoPointSource_USER = 2, + /* Network/external */ + meshtastic_GeoPointSource_GeoPointSource_NETWORK = 3 +} meshtastic_GeoPointSource; + /* Struct definitions */ /* ATAK GeoChat message */ typedef struct _meshtastic_GeoChat { @@ -146,6 +337,95 @@ typedef struct _meshtastic_TAKPacket { } payload_variant; } meshtastic_TAKPacket; +/* Aircraft track information from ADS-B or military air tracking. + Covers the majority of observed real-world CoT traffic. */ +typedef struct _meshtastic_AircraftTrack { + /* ICAO hex identifier (e.g. "AD237C") */ + char icao[8]; + /* Aircraft registration (e.g. "N946AK") */ + char registration[16]; + /* Flight number/callsign (e.g. "ASA864") */ + char flight[16]; + /* ICAO aircraft type designator (e.g. "B39M") */ + char aircraft_type[8]; + /* Transponder squawk code (0-7777 octal) */ + uint16_t squawk; + /* ADS-B emitter category (e.g. "A3") */ + char category[4]; + /* Received signal strength * 10 (e.g. -194 for -19.4 dBm) */ + int32_t rssi_x10; + /* Whether receiver has GPS fix */ + bool gps; + /* CoT host ID for source attribution */ + char cot_host_id[64]; +} meshtastic_AircraftTrack; + +typedef PB_BYTES_ARRAY_T(220) meshtastic_TAKPacketV2_raw_detail_t; +/* ATAK v2 packet with expanded CoT field support and zstd dictionary compression. + Sent on ATAK_PLUGIN_V2 port. The wire payload is: + [1 byte flags][zstd-compressed TAKPacketV2 protobuf] + Flags byte: bits 0-5 = dictionary ID, bits 6-7 = reserved. */ +typedef struct _meshtastic_TAKPacketV2 { + /* Well-known CoT event type enum. + Use CotType_Other with cot_type_str for unknown types. */ + meshtastic_CotType cot_type_id; + /* How the coordinates were generated */ + meshtastic_CotHow how; + /* Callsign */ + char callsign[120]; + /* Team color assignment */ + meshtastic_Team team; + /* Role of the group member */ + meshtastic_MemberRole role; + /* Latitude, multiply by 1e-7 to get degrees in floating point */ + int32_t latitude_i; + /* Longitude, multiply by 1e-7 to get degrees in floating point */ + int32_t longitude_i; + /* Altitude in meters (HAE) */ + int32_t altitude; + /* Speed in cm/s */ + uint32_t speed; + /* Course in degrees * 100 (0-36000) */ + uint16_t course; + /* Battery level 0-100 */ + uint8_t battery; + /* Geopoint source */ + meshtastic_GeoPointSource geo_src; + /* Altitude source */ + meshtastic_GeoPointSource alt_src; + /* Device UID (UUID string or device ID like "ANDROID-xxxx") */ + char uid[48]; + /* Device callsign */ + char device_callsign[120]; + /* Stale time as seconds offset from event time */ + uint16_t stale_seconds; + /* TAK client version string */ + char tak_version[64]; + /* TAK device model */ + char tak_device[32]; + /* TAK platform (ATAK-CIV, WebTAK, etc.) */ + char tak_platform[32]; + /* TAK OS version */ + char tak_os[16]; + /* Connection endpoint */ + char endpoint[32]; + /* Phone number */ + char phone[20]; + /* CoT event type string, only populated when cot_type_id is CotType_Other */ + char cot_type_str[32]; + pb_size_t which_payload_variant; + union { + /* Position report (true = PLI, no extra fields beyond the common ones above) */ + bool pli; + /* ATAK GeoChat message */ + meshtastic_GeoChat chat; + /* Aircraft track data (ADS-B, military air) */ + meshtastic_AircraftTrack aircraft; + /* Generic CoT detail XML for unmapped types */ + meshtastic_TAKPacketV2_raw_detail_t raw_detail; + } payload_variant; +} meshtastic_TAKPacketV2; + #ifdef __cplusplus extern "C" { @@ -160,6 +440,18 @@ extern "C" { #define _meshtastic_MemberRole_MAX meshtastic_MemberRole_K9 #define _meshtastic_MemberRole_ARRAYSIZE ((meshtastic_MemberRole)(meshtastic_MemberRole_K9+1)) +#define _meshtastic_CotHow_MIN meshtastic_CotHow_CotHow_Unspecified +#define _meshtastic_CotHow_MAX meshtastic_CotHow_CotHow_m_s +#define _meshtastic_CotHow_ARRAYSIZE ((meshtastic_CotHow)(meshtastic_CotHow_CotHow_m_s+1)) + +#define _meshtastic_CotType_MIN meshtastic_CotType_CotType_Other +#define _meshtastic_CotType_MAX meshtastic_CotType_CotType_b_f_t_a +#define _meshtastic_CotType_ARRAYSIZE ((meshtastic_CotType)(meshtastic_CotType_CotType_b_f_t_a+1)) + +#define _meshtastic_GeoPointSource_MIN meshtastic_GeoPointSource_GeoPointSource_Unspecified +#define _meshtastic_GeoPointSource_MAX meshtastic_GeoPointSource_GeoPointSource_NETWORK +#define _meshtastic_GeoPointSource_ARRAYSIZE ((meshtastic_GeoPointSource)(meshtastic_GeoPointSource_GeoPointSource_NETWORK+1)) + #define meshtastic_Group_role_ENUMTYPE meshtastic_MemberRole @@ -169,6 +461,14 @@ extern "C" { +#define meshtastic_TAKPacketV2_cot_type_id_ENUMTYPE meshtastic_CotType +#define meshtastic_TAKPacketV2_how_ENUMTYPE meshtastic_CotHow +#define meshtastic_TAKPacketV2_team_ENUMTYPE meshtastic_Team +#define meshtastic_TAKPacketV2_role_ENUMTYPE meshtastic_MemberRole +#define meshtastic_TAKPacketV2_geo_src_ENUMTYPE meshtastic_GeoPointSource +#define meshtastic_TAKPacketV2_alt_src_ENUMTYPE meshtastic_GeoPointSource + + /* Initializer values for message structs */ #define meshtastic_TAKPacket_init_default {0, false, meshtastic_Contact_init_default, false, meshtastic_Group_init_default, false, meshtastic_Status_init_default, 0, {meshtastic_PLI_init_default}} #define meshtastic_GeoChat_init_default {"", false, "", false, ""} @@ -176,12 +476,16 @@ extern "C" { #define meshtastic_Status_init_default {0} #define meshtastic_Contact_init_default {"", ""} #define meshtastic_PLI_init_default {0, 0, 0, 0, 0} +#define meshtastic_AircraftTrack_init_default {"", "", "", "", 0, "", 0, 0, ""} +#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", 0, {0}} #define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}} #define meshtastic_GeoChat_init_zero {"", false, "", false, ""} #define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN} #define meshtastic_Status_init_zero {0} #define meshtastic_Contact_init_zero {"", ""} #define meshtastic_PLI_init_zero {0, 0, 0, 0, 0} +#define meshtastic_AircraftTrack_init_zero {"", "", "", "", 0, "", 0, 0, ""} +#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", 0, {0}} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_GeoChat_message_tag 1 @@ -204,6 +508,42 @@ extern "C" { #define meshtastic_TAKPacket_pli_tag 5 #define meshtastic_TAKPacket_chat_tag 6 #define meshtastic_TAKPacket_detail_tag 7 +#define meshtastic_AircraftTrack_icao_tag 1 +#define meshtastic_AircraftTrack_registration_tag 2 +#define meshtastic_AircraftTrack_flight_tag 3 +#define meshtastic_AircraftTrack_aircraft_type_tag 4 +#define meshtastic_AircraftTrack_squawk_tag 5 +#define meshtastic_AircraftTrack_category_tag 6 +#define meshtastic_AircraftTrack_rssi_x10_tag 7 +#define meshtastic_AircraftTrack_gps_tag 8 +#define meshtastic_AircraftTrack_cot_host_id_tag 9 +#define meshtastic_TAKPacketV2_cot_type_id_tag 1 +#define meshtastic_TAKPacketV2_how_tag 2 +#define meshtastic_TAKPacketV2_callsign_tag 3 +#define meshtastic_TAKPacketV2_team_tag 4 +#define meshtastic_TAKPacketV2_role_tag 5 +#define meshtastic_TAKPacketV2_latitude_i_tag 6 +#define meshtastic_TAKPacketV2_longitude_i_tag 7 +#define meshtastic_TAKPacketV2_altitude_tag 8 +#define meshtastic_TAKPacketV2_speed_tag 9 +#define meshtastic_TAKPacketV2_course_tag 10 +#define meshtastic_TAKPacketV2_battery_tag 11 +#define meshtastic_TAKPacketV2_geo_src_tag 12 +#define meshtastic_TAKPacketV2_alt_src_tag 13 +#define meshtastic_TAKPacketV2_uid_tag 14 +#define meshtastic_TAKPacketV2_device_callsign_tag 15 +#define meshtastic_TAKPacketV2_stale_seconds_tag 16 +#define meshtastic_TAKPacketV2_tak_version_tag 17 +#define meshtastic_TAKPacketV2_tak_device_tag 18 +#define meshtastic_TAKPacketV2_tak_platform_tag 19 +#define meshtastic_TAKPacketV2_tak_os_tag 20 +#define meshtastic_TAKPacketV2_endpoint_tag 21 +#define meshtastic_TAKPacketV2_phone_tag 22 +#define meshtastic_TAKPacketV2_cot_type_str_tag 23 +#define meshtastic_TAKPacketV2_pli_tag 30 +#define meshtastic_TAKPacketV2_chat_tag 31 +#define meshtastic_TAKPacketV2_aircraft_tag 32 +#define meshtastic_TAKPacketV2_raw_detail_tag 33 /* Struct field encoding specification for nanopb */ #define meshtastic_TAKPacket_FIELDLIST(X, a) \ @@ -255,12 +595,60 @@ X(a, STATIC, SINGULAR, UINT32, course, 5) #define meshtastic_PLI_CALLBACK NULL #define meshtastic_PLI_DEFAULT NULL +#define meshtastic_AircraftTrack_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, icao, 1) \ +X(a, STATIC, SINGULAR, STRING, registration, 2) \ +X(a, STATIC, SINGULAR, STRING, flight, 3) \ +X(a, STATIC, SINGULAR, STRING, aircraft_type, 4) \ +X(a, STATIC, SINGULAR, UINT32, squawk, 5) \ +X(a, STATIC, SINGULAR, STRING, category, 6) \ +X(a, STATIC, SINGULAR, SINT32, rssi_x10, 7) \ +X(a, STATIC, SINGULAR, BOOL, gps, 8) \ +X(a, STATIC, SINGULAR, STRING, cot_host_id, 9) +#define meshtastic_AircraftTrack_CALLBACK NULL +#define meshtastic_AircraftTrack_DEFAULT NULL + +#define meshtastic_TAKPacketV2_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, cot_type_id, 1) \ +X(a, STATIC, SINGULAR, UENUM, how, 2) \ +X(a, STATIC, SINGULAR, STRING, callsign, 3) \ +X(a, STATIC, SINGULAR, UENUM, team, 4) \ +X(a, STATIC, SINGULAR, UENUM, role, 5) \ +X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 6) \ +X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 7) \ +X(a, STATIC, SINGULAR, SINT32, altitude, 8) \ +X(a, STATIC, SINGULAR, UINT32, speed, 9) \ +X(a, STATIC, SINGULAR, UINT32, course, 10) \ +X(a, STATIC, SINGULAR, UINT32, battery, 11) \ +X(a, STATIC, SINGULAR, UENUM, geo_src, 12) \ +X(a, STATIC, SINGULAR, UENUM, alt_src, 13) \ +X(a, STATIC, SINGULAR, STRING, uid, 14) \ +X(a, STATIC, SINGULAR, STRING, device_callsign, 15) \ +X(a, STATIC, SINGULAR, UINT32, stale_seconds, 16) \ +X(a, STATIC, SINGULAR, STRING, tak_version, 17) \ +X(a, STATIC, SINGULAR, STRING, tak_device, 18) \ +X(a, STATIC, SINGULAR, STRING, tak_platform, 19) \ +X(a, STATIC, SINGULAR, STRING, tak_os, 20) \ +X(a, STATIC, SINGULAR, STRING, endpoint, 21) \ +X(a, STATIC, SINGULAR, STRING, phone, 22) \ +X(a, STATIC, SINGULAR, STRING, cot_type_str, 23) \ +X(a, STATIC, ONEOF, BOOL, (payload_variant,pli,payload_variant.pli), 30) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 31) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,aircraft,payload_variant.aircraft), 32) \ +X(a, STATIC, ONEOF, BYTES, (payload_variant,raw_detail,payload_variant.raw_detail), 33) +#define meshtastic_TAKPacketV2_CALLBACK NULL +#define meshtastic_TAKPacketV2_DEFAULT NULL +#define meshtastic_TAKPacketV2_payload_variant_chat_MSGTYPE meshtastic_GeoChat +#define meshtastic_TAKPacketV2_payload_variant_aircraft_MSGTYPE meshtastic_AircraftTrack + extern const pb_msgdesc_t meshtastic_TAKPacket_msg; extern const pb_msgdesc_t meshtastic_GeoChat_msg; extern const pb_msgdesc_t meshtastic_Group_msg; extern const pb_msgdesc_t meshtastic_Status_msg; extern const pb_msgdesc_t meshtastic_Contact_msg; extern const pb_msgdesc_t meshtastic_PLI_msg; +extern const pb_msgdesc_t meshtastic_AircraftTrack_msg; +extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_TAKPacket_fields &meshtastic_TAKPacket_msg @@ -269,14 +657,18 @@ extern const pb_msgdesc_t meshtastic_PLI_msg; #define meshtastic_Status_fields &meshtastic_Status_msg #define meshtastic_Contact_fields &meshtastic_Contact_msg #define meshtastic_PLI_fields &meshtastic_PLI_msg +#define meshtastic_AircraftTrack_fields &meshtastic_AircraftTrack_msg +#define meshtastic_TAKPacketV2_fields &meshtastic_TAKPacketV2_msg /* Maximum encoded size of messages (where known) */ -#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_TAKPacket_size +#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_TAKPacketV2_size +#define meshtastic_AircraftTrack_size 134 #define meshtastic_Contact_size 242 #define meshtastic_GeoChat_size 444 #define meshtastic_Group_size 4 #define meshtastic_PLI_size 31 #define meshtastic_Status_size 3 +#define meshtastic_TAKPacketV2_size 1027 #define meshtastic_TAKPacket_size 705 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 477c3b31b..fc6931d73 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -308,6 +308,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_TDISPLAY_S3_PRO = 126, /* Heltec Mesh Node T096 board features an nRF52840 CPU and a TFT screen. */ meshtastic_HardwareModel_HELTEC_MESH_NODE_T096 = 127, + /* Seeed studio T1000-E Pro tracker card. NRF52840 w/ LR2021 radio, GPS, button, buzzer, and sensors. */ + meshtastic_HardwareModel_TRACKER_T1000_E_PRO = 128, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index bd1fe48c4..a474e5b92 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -150,6 +150,10 @@ typedef enum _meshtastic_PortNum { arbitrary telemetry over meshtastic that is not covered by telemetry.proto ENCODING: CayenneLLP */ meshtastic_PortNum_CAYENNE_APP = 77, + /* ATAK Plugin V2 + Portnum for payloads from the official Meshtastic ATAK plugin using + TAKPacketV2 with zstd dictionary compression. */ + meshtastic_PortNum_ATAK_PLUGIN_V2 = 78, /* GroupAlarm integration Used for transporting GroupAlarm-related messages between Meshtastic nodes and companion applications/services. */ diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 3addc4b3a..16ccdd744 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -203,6 +203,10 @@ void ExternalNotificationModule::setExternalState(uint8_t index, bool on) default: if (output > 0) digitalWrite(output, (moduleConfig.external_notification.active ? on : !on)); +#ifdef PCA_LED_NOTIFICATION + io.digitalWrite(PCA_LED_NOTIFICATION, on); + +#endif break; } diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index 7a969343e..20d4d7d8c 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -651,7 +651,7 @@ void SerialModule::processWXSerial() LOG_INFO("WS8X : %i %.1fg%.1f %.1fv %.1fv %.1fC rain: %.1f, %i sum", atoi(windDir), strtof(windVel, nullptr), strtof(windGust, nullptr), batVoltageF, capVoltageF, temperatureF, rain, rainSum); } - if (gotwind && !Throttle::isWithinTimespanMs(lastAveraged, averageIntervalMillis)) { + if (gotwind && !Throttle::isWithinTimespanMs(lastAveraged, averageIntervalMillis) && velCount > 0 && dirCount > 0) { // calculate averages and send to the mesh float velAvg = 1.0 * velSum / velCount; diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index b7b6e04a9..684d408a1 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -66,18 +66,10 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c #include "Sensor/MCP9808Sensor.h" #endif -#if __has_include() -#include "Sensor/SHT31Sensor.h" -#endif - #if __has_include() #include "Sensor/LPS22HBSensor.h" #endif -#if __has_include() -#include "Sensor/SHTC3Sensor.h" -#endif - #if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1 #include "Sensor/RAK12035Sensor.h" #endif @@ -94,8 +86,8 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c #include "Sensor/OPT3001Sensor.h" #endif -#if __has_include() -#include "Sensor/SHT4XSensor.h" +#if __has_include() +#include "Sensor/SHTXXSensor.h" #endif #if __has_include() @@ -155,6 +147,15 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner) } LOG_INFO("Environment Telemetry adding I2C devices..."); + /* + Uncomment the preferences below if you want to use the module + without having to configure it from the PythonAPI or WebUI. + */ + + // moduleConfig.telemetry.environment_measurement_enabled = 1; + // moduleConfig.telemetry.environment_screen_enabled = 1; + // moduleConfig.telemetry.environment_update_interval = 15; + // order by priority of metrics/values (low top, high bottom) #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR @@ -202,15 +203,9 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner) #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::MCP9808); #endif -#if __has_include() - addSensor(i2cScanner, ScanI2C::DeviceType::SHT31); -#endif #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::LPS22HB); #endif -#if __has_include() - addSensor(i2cScanner, ScanI2C::DeviceType::SHTC3); -#endif #if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1 addSensor(i2cScanner, ScanI2C::DeviceType::RAK12035); #endif @@ -223,13 +218,9 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner) #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::OPT3001); #endif -#if __has_include() - addSensor(i2cScanner, ScanI2C::DeviceType::SHT4X); -#endif #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::MLX90632); #endif - #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::BMP_3XX); #endif @@ -245,7 +236,10 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner) #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::BH1750); #endif - +#if __has_include() + // TODO Can we scan for multiple sensors connected on the same bus? + addSensor(i2cScanner, ScanI2C::DeviceType::SHTXX); +#endif #endif } @@ -260,14 +254,6 @@ int32_t EnvironmentTelemetryModule::runOnce() } uint32_t result = UINT32_MAX; - /* - Uncomment the preferences below if you want to use the module - without having to configure it from the PythonAPI or WebUI. - */ - - // moduleConfig.telemetry.environment_measurement_enabled = 1; - // moduleConfig.telemetry.environment_screen_enabled = 1; - // moduleConfig.telemetry.environment_update_interval = 15; if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled || ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE)) { diff --git a/src/modules/Telemetry/Sensor/SHT31Sensor.cpp b/src/modules/Telemetry/Sensor/SHT31Sensor.cpp deleted file mode 100644 index 67a36933d..000000000 --- a/src/modules/Telemetry/Sensor/SHT31Sensor.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "SHT31Sensor.h" -#include "TelemetrySensor.h" -#include - -SHT31Sensor::SHT31Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHT31, "SHT31") {} - -bool SHT31Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) -{ - LOG_INFO("Init sensor: %s", sensorName); - sht31 = Adafruit_SHT31(bus); - status = sht31.begin(dev->address.address); - initI2CSensor(); - return status; -} - -bool SHT31Sensor::getMetrics(meshtastic_Telemetry *measurement) -{ - measurement->variant.environment_metrics.has_temperature = true; - measurement->variant.environment_metrics.has_relative_humidity = true; - measurement->variant.environment_metrics.temperature = sht31.readTemperature(); - measurement->variant.environment_metrics.relative_humidity = sht31.readHumidity(); - - return true; -} - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHT31Sensor.h b/src/modules/Telemetry/Sensor/SHT31Sensor.h deleted file mode 100644 index ecb7d63a6..000000000 --- a/src/modules/Telemetry/Sensor/SHT31Sensor.h +++ /dev/null @@ -1,20 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "TelemetrySensor.h" -#include - -class SHT31Sensor : public TelemetrySensor -{ - private: - Adafruit_SHT31 sht31; - - public: - SHT31Sensor(); - virtual bool getMetrics(meshtastic_Telemetry *measurement) override; - virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override; -}; - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHT4XSensor.cpp b/src/modules/Telemetry/Sensor/SHT4XSensor.cpp deleted file mode 100644 index b11795d97..000000000 --- a/src/modules/Telemetry/Sensor/SHT4XSensor.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "SHT4XSensor.h" -#include "TelemetrySensor.h" -#include - -SHT4XSensor::SHT4XSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHT4X, "SHT4X") {} - -bool SHT4XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) -{ - LOG_INFO("Init sensor: %s", sensorName); - - uint32_t serialNumber = 0; - - status = sht4x.begin(bus); - if (!status) { - return status; - } - - serialNumber = sht4x.readSerial(); - if (serialNumber != 0) { - LOG_DEBUG("serialNumber : %x", serialNumber); - status = 1; - } else { - LOG_DEBUG("Error trying to execute readSerial(): "); - status = 0; - } - - initI2CSensor(); - return status; -} - -bool SHT4XSensor::getMetrics(meshtastic_Telemetry *measurement) -{ - measurement->variant.environment_metrics.has_temperature = true; - measurement->variant.environment_metrics.has_relative_humidity = true; - - sensors_event_t humidity, temp; - sht4x.getEvent(&humidity, &temp); - measurement->variant.environment_metrics.temperature = temp.temperature; - measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity; - return true; -} - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHT4XSensor.h b/src/modules/Telemetry/Sensor/SHT4XSensor.h deleted file mode 100644 index 7311d2366..000000000 --- a/src/modules/Telemetry/Sensor/SHT4XSensor.h +++ /dev/null @@ -1,20 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "TelemetrySensor.h" -#include - -class SHT4XSensor : public TelemetrySensor -{ - private: - Adafruit_SHT4x sht4x = Adafruit_SHT4x(); - - public: - SHT4XSensor(); - virtual bool getMetrics(meshtastic_Telemetry *measurement) override; - virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override; -}; - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp b/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp deleted file mode 100644 index fdab0b266..000000000 --- a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "SHTC3Sensor.h" -#include "TelemetrySensor.h" -#include - -SHTC3Sensor::SHTC3Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHTC3, "SHTC3") {} - -bool SHTC3Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) -{ - LOG_INFO("Init sensor: %s", sensorName); - status = shtc3.begin(bus); - - initI2CSensor(); - return status; -} - -bool SHTC3Sensor::getMetrics(meshtastic_Telemetry *measurement) -{ - measurement->variant.environment_metrics.has_temperature = true; - measurement->variant.environment_metrics.has_relative_humidity = true; - - sensors_event_t humidity, temp; - shtc3.getEvent(&humidity, &temp); - - measurement->variant.environment_metrics.temperature = temp.temperature; - measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity; - - return true; -} - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.h b/src/modules/Telemetry/Sensor/SHTC3Sensor.h deleted file mode 100644 index 51cee18f7..000000000 --- a/src/modules/Telemetry/Sensor/SHTC3Sensor.h +++ /dev/null @@ -1,20 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "TelemetrySensor.h" -#include - -class SHTC3Sensor : public TelemetrySensor -{ - private: - Adafruit_SHTC3 shtc3 = Adafruit_SHTC3(); - - public: - SHTC3Sensor(); - virtual bool getMetrics(meshtastic_Telemetry *measurement) override; - virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override; -}; - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHTXXSensor.cpp b/src/modules/Telemetry/Sensor/SHTXXSensor.cpp new file mode 100644 index 000000000..92cac7f77 --- /dev/null +++ b/src/modules/Telemetry/Sensor/SHTXXSensor.cpp @@ -0,0 +1,145 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "SHTXXSensor.h" +#include "TelemetrySensor.h" +#include + +SHTXXSensor::SHTXXSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHTXX, "SHTXX") {} + +void SHTXXSensor::getSensorVariant(SHTSensor::SHTSensorType sensorType) +{ + switch (sensorType) { + case SHTSensor::SHTSensorType::SHT2X: + sensorVariant = "SHT2x"; + break; + + case SHTSensor::SHTSensorType::SHT3X: + case SHTSensor::SHTSensorType::SHT85: + sensorVariant = "SHT3x/SHT85"; + break; + + case SHTSensor::SHTSensorType::SHT3X_ALT: + sensorVariant = "SHT3x"; + break; + + case SHTSensor::SHTSensorType::SHTW1: + case SHTSensor::SHTSensorType::SHTW2: + case SHTSensor::SHTSensorType::SHTC1: + case SHTSensor::SHTSensorType::SHTC3: + sensorVariant = "SHTC1/SHTC3/SHTW1/SHTW2"; + break; + + case SHTSensor::SHTSensorType::SHT4X: + sensorVariant = "SHT4x"; + break; + + default: + sensorVariant = "Unknown"; + break; + } +} + +bool SHTXXSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) +{ + LOG_INFO("Init sensor: %s", sensorName); + + _bus = bus; + _address = dev->address.address; + + if (sht.init(*_bus)) { + LOG_INFO("%s: init(): success", sensorName); + getSensorVariant(sht.mSensorType); + LOG_INFO("%s Sensor detected: %s on 0x%x", sensorName, sensorVariant, _address); + status = 1; + } else { + LOG_ERROR("%s: init(): failed", sensorName); + } + + initI2CSensor(); + return status; +} + +/** + * Accuracy setting of measurement. + * Not all sensors support changing the sampling accuracy (only SHT3X and SHT4X) + * SHTAccuracy: + * - SHT_ACCURACY_HIGH: Highest repeatability at the cost of slower measurement + * - SHT_ACCURACY_MEDIUM: Balanced repeatability and speed of measurement + * - SHT_ACCURACY_LOW: Fastest measurement but lowest repeatability + */ +bool SHTXXSensor::setAccuracy(SHTSensor::SHTAccuracy newAccuracy) +{ + // Only SHT3X-family (including alternates) and SHT4X support changing accuracy + if (sht.mSensorType != SHTSensor::SHTSensorType::SHT3X && sht.mSensorType != SHTSensor::SHTSensorType::SHT3X_ALT && + sht.mSensorType != SHTSensor::SHTSensorType::SHT85 && sht.mSensorType != SHTSensor::SHTSensorType::SHT4X) { + LOG_WARN("%s doesn't support accuracy setting", sensorVariant); + return false; + } + LOG_INFO("%s: setting new accuracy setting", sensorVariant); + accuracy = newAccuracy; + return sht.setAccuracy(accuracy); +} + +bool SHTXXSensor::getMetrics(meshtastic_Telemetry *measurement) +{ + if (sht.readSample()) { + measurement->variant.environment_metrics.has_temperature = true; + measurement->variant.environment_metrics.has_relative_humidity = true; + measurement->variant.environment_metrics.temperature = sht.getTemperature(); + measurement->variant.environment_metrics.relative_humidity = sht.getHumidity(); + + LOG_INFO("%s (%s): Got: temp:%fdegC, hum:%f%%rh", sensorName, sensorVariant, + measurement->variant.environment_metrics.temperature, + measurement->variant.environment_metrics.relative_humidity); + + return true; + } else { + LOG_ERROR("%s (%s): read sample failed", sensorName, sensorVariant); + return false; + } +} + +AdminMessageHandleResult SHTXXSensor::handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, + meshtastic_AdminMessage *response) +{ + AdminMessageHandleResult result; + result = AdminMessageHandleResult::NOT_HANDLED; + + switch (request->which_payload_variant) { + case meshtastic_AdminMessage_sensor_config_tag: + if (!request->sensor_config.has_shtxx_config) { + result = AdminMessageHandleResult::NOT_HANDLED; + break; + } + + // Check for sensor accuracy setting + if (request->sensor_config.shtxx_config.has_set_accuracy) { + SHTSensor::SHTAccuracy newAccuracy; + if (request->sensor_config.shtxx_config.set_accuracy == 0) { + newAccuracy = SHTSensor::SHT_ACCURACY_LOW; + } else if (request->sensor_config.shtxx_config.set_accuracy == 1) { + newAccuracy = SHTSensor::SHT_ACCURACY_MEDIUM; + } else if (request->sensor_config.shtxx_config.set_accuracy == 2) { + newAccuracy = SHTSensor::SHT_ACCURACY_HIGH; + } else { + LOG_ERROR("%s: incorrect accuracy setting", sensorName); + result = AdminMessageHandleResult::HANDLED; + break; + } + this->setAccuracy(newAccuracy); + } + + result = AdminMessageHandleResult::HANDLED; + break; + + default: + result = AdminMessageHandleResult::NOT_HANDLED; + } + + return result; +} + +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/SHTXXSensor.h b/src/modules/Telemetry/Sensor/SHTXXSensor.h new file mode 100644 index 000000000..e354e113f --- /dev/null +++ b/src/modules/Telemetry/Sensor/SHTXXSensor.h @@ -0,0 +1,29 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" +#include + +class SHTXXSensor : public TelemetrySensor +{ + private: + SHTSensor sht; + TwoWire *_bus{}; + uint8_t _address{}; + SHTSensor::SHTAccuracy accuracy{}; + bool setAccuracy(SHTSensor::SHTAccuracy newAccuracy); + + public: + SHTXXSensor(); + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; + virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override; + void getSensorVariant(SHTSensor::SHTSensorType); + const char *sensorVariant{}; + + AdminMessageHandleResult handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, + meshtastic_AdminMessage *response) override; +}; + +#endif \ No newline at end of file diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index c916f86c4..15762c93d 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -321,8 +321,8 @@ bool connectPubSub(const PubSubConfig &config, PubSubClient &pubSub, Client &cli pubSub.setClient(client); pubSub.setServer(config.serverAddr.c_str(), config.serverPort); - LOG_INFO("Connecting directly to MQTT server %s, port: %d, username: %s, password: %s", config.serverAddr.c_str(), - config.serverPort, config.mqttUsername, config.mqttPassword); + LOG_INFO("Connecting directly to MQTT server %s, port: %d, username: %s, password: ***", config.serverAddr.c_str(), + config.serverPort, config.mqttUsername); // Generate node ID from nodenum for client identification std::string nodeId = nodeDB->getNodeId(); diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp index 01193b9a1..c57cc685e 100644 --- a/src/platform/esp32/main-esp32.cpp +++ b/src/platform/esp32/main-esp32.cpp @@ -232,7 +232,9 @@ void cpuDeepSleep(uint32_t msecToWake) #if SOC_RTCIO_HOLD_SUPPORTED && SOC_PM_SUPPORT_EXT_WAKEUP uint64_t gpioMask = (1ULL << (config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN)); #endif - +#ifdef ALT_BUTTON_WAKE + gpioMask |= (1ULL << BUTTON_PIN_ALT); +#endif #ifdef BUTTON_NEED_PULLUP gpio_pullup_en((gpio_num_t)BUTTON_PIN); #endif diff --git a/src/platform/extra_variants/t_lora_pager/variant.cpp b/src/platform/extra_variants/t_lora_pager/variant.cpp index ea5773d30..19c8881ca 100644 --- a/src/platform/extra_variants/t_lora_pager/variant.cpp +++ b/src/platform/extra_variants/t_lora_pager/variant.cpp @@ -23,5 +23,6 @@ void lateInitVariant() cfg.i2s.bits = BIT_LENGTH_16BITS; cfg.i2s.rate = RATE_44K; board.begin(cfg); + board.setVolume(75); // 75% volume } #endif \ No newline at end of file diff --git a/src/platform/stm32wl/hardfault_handler.s b/src/platform/stm32wl/hardfault_handler.s new file mode 100644 index 000000000..ab76096fa --- /dev/null +++ b/src/platform/stm32wl/hardfault_handler.s @@ -0,0 +1,11 @@ +.globl HardFault_Handler +.syntax unified +.thumb + +.type HardFault_Handler, %function +HardFault_Handler: +tst lr, #4 +ite eq +mrseq r0, msp +mrsne r0, psp +b HardFault_Handler_C \ No newline at end of file diff --git a/src/platform/stm32wl/main-stm32wl.cpp b/src/platform/stm32wl/main-stm32wl.cpp index e841f8f29..93080f840 100644 --- a/src/platform/stm32wl/main-stm32wl.cpp +++ b/src/platform/stm32wl/main-stm32wl.cpp @@ -1,5 +1,6 @@ #include "RTC.h" #include "configuration.h" +#include #include #include @@ -53,4 +54,99 @@ extern "C" void __wrap__tzset_unlocked_r(struct _reent *reent_ptr) { return; } -#endif \ No newline at end of file +#endif + +// Taken from https://interrupt.memfault.com/blog/cortex-m-hardfault-debug +typedef struct __attribute__((packed)) ContextStateFrame { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t return_address; + uint32_t xpsr; +} sContextStateFrame; + +// NOTE: If you are using CMSIS, the registers can also be +// accessed through CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk +#define HALT_IF_DEBUGGING() \ + do { \ + if ((*(volatile uint32_t *)0xE000EDF0) & (1 << 0)) { \ + __asm("bkpt 1"); \ + } \ + } while (0) + +static char hardfault_message_buffer[256]; + +// printf directly using srcwrapper's debug UART function. +static void debug_printf(const char *format, ...) +{ + va_list args; + va_start(args, format); + int length = vsnprintf(hardfault_message_buffer, sizeof(hardfault_message_buffer), format, args); + va_end(args); + + if (length < 0) + return; + uart_debug_write((uint8_t *)hardfault_message_buffer, min((unsigned int)length, sizeof(hardfault_message_buffer) - 1)); +} + +// N picked by guessing +#define DOT_TIME 1200000 +static void dot() +{ + digitalWrite(LED_POWER, LED_STATE_ON); + for (volatile int i = 0; i < DOT_TIME; i++) { /* busy wait */ + } + digitalWrite(LED_POWER, LED_STATE_OFF); + for (volatile int i = 0; i < DOT_TIME; i++) { /* busy wait */ + } +} + +static void dash() +{ + digitalWrite(LED_POWER, LED_STATE_ON); + for (volatile int i = 0; i < (DOT_TIME * 3); i++) { /* busy wait */ + } + digitalWrite(LED_POWER, LED_STATE_OFF); + for (volatile int i = 0; i < DOT_TIME; i++) { /* busy wait */ + } +} + +static void space() +{ + for (volatile int i = 0; i < (DOT_TIME * 3); i++) { /* busy wait */ + } +} + +// Disable optimizations for this function so "frame" argument +// does not get optimized away +extern "C" __attribute__((optimize("O0"))) void HardFault_Handler_C(sContextStateFrame *frame) +{ + debug_printf("HardFault!\r\n"); + debug_printf("r0: %08x\r\n", frame->r0); + debug_printf("r1: %08x\r\n", frame->r1); + debug_printf("r2: %08x\r\n", frame->r2); + debug_printf("r3: %08x\r\n", frame->r3); + debug_printf("r12: %08x\r\n", frame->r12); + debug_printf("lr: %08x\r\n", frame->lr); + debug_printf("pc[return address]: %08x\r\n", frame->return_address); + debug_printf("xpsr: %08x\r\n", frame->xpsr); + + HALT_IF_DEBUGGING(); + + // blink SOS forever + while (1) { + dot(); + dot(); + dot(); + dash(); + dash(); + dash(); + dot(); + dot(); + dot(); + space(); + } +} \ No newline at end of file diff --git a/test/test_radio/test_main.cpp b/test/test_radio/test_main.cpp index 49eaabe5b..a7d3d32d2 100644 --- a/test/test_radio/test_main.cpp +++ b/test/test_radio/test_main.cpp @@ -14,6 +14,23 @@ class MockMeshService : public MeshService static MockMeshService *mockMeshService; +// Test shim to expose protected radio parameters set by applyModemConfig() +class TestableRadioInterface : public RadioInterface +{ + public: + TestableRadioInterface() : RadioInterface() {} + uint8_t getCr() const { return cr; } + uint8_t getSf() const { return sf; } + float getBw() const { return bw; } + + // Override reconfigure to call the base which invokes applyModemConfig() + bool reconfigure() override { return RadioInterface::reconfigure(); } + + // Stubs for pure virtual methods required by RadioInterface + uint32_t getPacketTime(uint32_t, bool) override { return 0; } + ErrorCode send(meshtastic_MeshPacket *p) override { return ERRNO_OK; } +}; + static void test_bwCodeToKHz_specialMappings() { TEST_ASSERT_FLOAT_WITHIN(0.0001f, 31.25f, bwCodeToKHz(31)); @@ -100,13 +117,87 @@ static void test_clampConfigLora_validPresetUnchanged() TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, cfg.modem_preset); } +// ----------------------------------------------------------------------- +// applyModemConfig() coding rate tests (via reconfigure) +// ----------------------------------------------------------------------- + +static TestableRadioInterface *testRadio; + +// After fresh flash: coding_rate=0, use_preset=true, modem_preset=LONG_FAST +// CR should come from the preset (5 for LONG_FAST), not from the zero default. +static void test_applyModemConfig_freshFlashCodingRateNotZero() +{ + config.lora = meshtastic_Config_LoRaConfig_init_zero; + config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US; + config.lora.use_preset = true; + config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + // coding_rate is 0 (default after init_zero, same as fresh flash) + + testRadio->reconfigure(); + + // LONG_FAST preset has cr=5; must never be 0 + TEST_ASSERT_EQUAL_UINT8(5, testRadio->getCr()); + TEST_ASSERT_EQUAL_UINT8(11, testRadio->getSf()); + TEST_ASSERT_FLOAT_WITHIN(0.01f, 250.0f, testRadio->getBw()); +} + +// When coding_rate matches the preset exactly, should still use the preset value +static void test_applyModemConfig_codingRateMatchesPreset() +{ + config.lora = meshtastic_Config_LoRaConfig_init_zero; + config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US; + config.lora.use_preset = true; + config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW; + config.lora.coding_rate = 8; // LONG_SLOW default is cr=8 + + testRadio->reconfigure(); + + TEST_ASSERT_EQUAL_UINT8(8, testRadio->getCr()); +} + +// Custom CR higher than preset should be used +static void test_applyModemConfig_customCodingRateHigherThanPreset() +{ + config.lora = meshtastic_Config_LoRaConfig_init_zero; + config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US; + config.lora.use_preset = true; + config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + config.lora.coding_rate = 7; // LONG_FAST preset has cr=5, 7 > 5 + + testRadio->reconfigure(); + + TEST_ASSERT_EQUAL_UINT8(7, testRadio->getCr()); +} + +// Custom CR lower than preset: preset wins (higher is more robust) +static void test_applyModemConfig_customCodingRateLowerThanPreset() +{ + config.lora = meshtastic_Config_LoRaConfig_init_zero; + config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US; + config.lora.use_preset = true; + config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW; + config.lora.coding_rate = 5; // LONG_SLOW preset has cr=8, 5 < 8 + + testRadio->reconfigure(); + + TEST_ASSERT_EQUAL_UINT8(8, testRadio->getCr()); +} + void setUp(void) { mockMeshService = new MockMeshService(); service = mockMeshService; + + // RadioInterface computes slotTimeMsec during construction and expects myRegion to be valid. + config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US; + initRegion(); + + testRadio = new TestableRadioInterface(); } void tearDown(void) { + delete testRadio; + testRadio = nullptr; service = nullptr; delete mockMeshService; mockMeshService = nullptr; @@ -128,6 +219,10 @@ void setup() RUN_TEST(test_validateConfigLora_rejectsInvalidPresetForRegion); RUN_TEST(test_clampConfigLora_invalidPresetClampedToDefault); RUN_TEST(test_clampConfigLora_validPresetUnchanged); + RUN_TEST(test_applyModemConfig_freshFlashCodingRateNotZero); + RUN_TEST(test_applyModemConfig_codingRateMatchesPreset); + RUN_TEST(test_applyModemConfig_customCodingRateHigherThanPreset); + RUN_TEST(test_applyModemConfig_customCodingRateLowerThanPreset); exit(UNITY_END()); } diff --git a/variants/esp32/esp32-common.ini b/variants/esp32/esp32-common.ini index de86501cf..0da40cef3 100644 --- a/variants/esp32/esp32-common.ini +++ b/variants/esp32/esp32-common.ini @@ -36,7 +36,6 @@ build_flags = -Wall -Wextra -Isrc/platform/esp32 - -include mbedtls/error.h -std=gnu++17 -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG @@ -58,8 +57,8 @@ lib_deps = ${environmental_base.lib_deps} ${environmental_extra.lib_deps} ${radiolib_base.lib_deps} - # TODO renovate - https://github.com/meshtastic/esp32_https_server/archive/e42e0bbca3eaa59672bfb42cda8e53a6f9a2266e.zip + # renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master + https://github.com/meshtastic/esp32_https_server/archive/0c71f380390ad483ff134ad938e07f6cf1226c5b.zip # renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino h2zero/NimBLE-Arduino@1.4.3 # TODO renovate diff --git a/variants/esp32/nano-g1-explorer/platformio.ini b/variants/esp32/nano-g1-explorer/platformio.ini index 16ecb99cc..b27ebf28e 100644 --- a/variants/esp32/nano-g1-explorer/platformio.ini +++ b/variants/esp32/nano-g1-explorer/platformio.ini @@ -9,7 +9,7 @@ custom_meshtastic_display_name = Nano G1 Explorer custom_meshtastic_tags = B&Q extends = esp32_base -board = ttgo-t-beam +board = ttgo-tbeam build_flags = ${esp32_base.build_flags} -D NANO_G1_EXPLORER diff --git a/variants/esp32/nano-g1/platformio.ini b/variants/esp32/nano-g1/platformio.ini index 724e008c7..b2e392dbd 100644 --- a/variants/esp32/nano-g1/platformio.ini +++ b/variants/esp32/nano-g1/platformio.ini @@ -9,7 +9,7 @@ custom_meshtastic_display_name = Nano G1 custom_meshtastic_tags = B&Q extends = esp32_base -board = ttgo-t-beam +board = ttgo-tbeam build_flags = ${esp32_base.build_flags} -D NANO_G1 diff --git a/variants/esp32/station-g1/platformio.ini b/variants/esp32/station-g1/platformio.ini index b1f3e15f3..5a7f33485 100644 --- a/variants/esp32/station-g1/platformio.ini +++ b/variants/esp32/station-g1/platformio.ini @@ -9,10 +9,7 @@ custom_meshtastic_display_name = Station G1 custom_meshtastic_tags = B&Q extends = esp32_base -board = ttgo-t-beam -build_unflags = - ${esp32_common.build_unflags} - -DBOARD_HAS_PSRAM +board = ttgo-tbeam build_flags = ${esp32_base.build_flags} -D STATION_G1 diff --git a/variants/esp32/tbeam/platformio.ini b/variants/esp32/tbeam/platformio.ini index 26c8e9cd3..c9e6cce1f 100644 --- a/variants/esp32/tbeam/platformio.ini +++ b/variants/esp32/tbeam/platformio.ini @@ -10,14 +10,12 @@ custom_meshtastic_images = tbeam.svg custom_meshtastic_tags = LilyGo extends = esp32_base -board = ttgo-t-beam +board = ttgo-tbeam board_check = true build_flags = ${esp32_base.build_flags} -D TBEAM_V10 -I variants/esp32/tbeam - -DBOARD_HAS_PSRAM - -mfix-esp32-psram-cache-issue -ULED_BUILTIN upload_speed = 921600 diff --git a/variants/esp32/tbeam_v07/platformio.ini b/variants/esp32/tbeam_v07/platformio.ini index e2763fdec..1809ba56c 100644 --- a/variants/esp32/tbeam_v07/platformio.ini +++ b/variants/esp32/tbeam_v07/platformio.ini @@ -9,7 +9,7 @@ custom_meshtastic_tags = LilyGo board_level = extra extends = esp32_base -board = ttgo-t-beam +board = ttgo-tbeam build_flags = ${esp32_base.build_flags} -D TBEAM_V07 diff --git a/variants/esp32s3/ELECROW-ThinkNode-M5/variant.cpp b/variants/esp32s3/ELECROW-ThinkNode-M5/variant.cpp index 917341560..51a91bef0 100644 --- a/variants/esp32s3/ELECROW-ThinkNode-M5/variant.cpp +++ b/variants/esp32s3/ELECROW-ThinkNode-M5/variant.cpp @@ -9,11 +9,11 @@ void earlyInitVariant() io.pinMode(PCA_PIN_EINK_EN, OUTPUT); io.pinMode(PCA_PIN_POWER_EN, OUTPUT); io.pinMode(PCA_LED_POWER, OUTPUT); - io.pinMode(PCA_LED_USER, OUTPUT); + io.pinMode(PCA_LED_NOTIFICATION, OUTPUT); io.pinMode(PCA_LED_ENABLE, OUTPUT); io.digitalWrite(PCA_PIN_POWER_EN, HIGH); - io.digitalWrite(PCA_LED_USER, LOW); + io.digitalWrite(PCA_LED_NOTIFICATION, LOW); io.digitalWrite(PCA_LED_ENABLE, LOW); } diff --git a/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h b/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h index ff3541713..55bcd0dc7 100644 --- a/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h +++ b/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h @@ -8,9 +8,9 @@ // LED // Both of these are on the GPIO expander -#define PCA_LED_USER 1 // the Blue LED -#define PCA_LED_ENABLE 2 // the power supply to the LEDs, in an OR arrangement with VBUS power -#define PCA_LED_POWER 3 // the Red LED? Seems to have hardware logic to blink when USB is plugged in. +#define PCA_LED_NOTIFICATION 1 // the Blue LED +#define PCA_LED_ENABLE 2 // the power supply to the LEDs, in an OR arrangement with VBUS power +#define PCA_LED_POWER 3 // the Red LED? Seems to have hardware logic to blink when USB is plugged in. #define POWER_LED_HARDWARE_BLINKS_WHILE_CHARGING // USB_CHECK @@ -18,7 +18,7 @@ #define BATTERY_PIN 8 #define ADC_CHANNEL ADC_CHANNEL_7 -#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. +#define ADC_MULTIPLIER 2.0 // 2.0 + 10% for correction of display undervoltage. #define PIN_BUZZER 9 @@ -86,6 +86,7 @@ #define BUTTON_PIN PIN_BUTTON1 #define BUTTON_PIN_ALT PIN_BUTTON2 +#define ALT_BUTTON_WAKE #define SERIAL_PRINT_PORT 0 #endif diff --git a/variants/esp32s3/elecrow_panel/platformio.ini b/variants/esp32s3/elecrow_panel/platformio.ini index 9d2d3f664..a707a832e 100644 --- a/variants/esp32s3/elecrow_panel/platformio.ini +++ b/variants/esp32s3/elecrow_panel/platformio.ini @@ -89,6 +89,7 @@ custom_meshtastic_images = crowpanel_2_4.svg, crowpanel_2_8.svg custom_meshtastic_tags = Elecrow custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = true extends = crowpanel_small_esp32s3_base build_flags = @@ -124,6 +125,7 @@ custom_meshtastic_images = crowpanel_3_5.svg custom_meshtastic_tags = Elecrow custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = true extends = crowpanel_small_esp32s3_base board_level = pr @@ -163,6 +165,7 @@ custom_meshtastic_images = crowpanel_5_0.svg, crowpanel_7_0.svg custom_meshtastic_tags = Elecrow custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = true extends = crowpanel_large_esp32s3_base build_flags = diff --git a/variants/esp32s3/heltec_v4/platformio.ini b/variants/esp32s3/heltec_v4/platformio.ini index cb795c65d..0336bf983 100644 --- a/variants/esp32s3/heltec_v4/platformio.ini +++ b/variants/esp32s3/heltec_v4/platformio.ini @@ -22,6 +22,7 @@ custom_meshtastic_images = heltec_v4.svg custom_meshtastic_tags = Heltec custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = true extends = heltec_v4_base build_flags = diff --git a/variants/esp32s3/heltec_vision_master_e213/platformio.ini b/variants/esp32s3/heltec_vision_master_e213/platformio.ini index 80655af70..fb97fd983 100644 --- a/variants/esp32s3/heltec_vision_master_e213/platformio.ini +++ b/variants/esp32s3/heltec_vision_master_e213/platformio.ini @@ -9,6 +9,7 @@ custom_meshtastic_images = heltec-vision-master-e213.svg custom_meshtastic_tags = Heltec custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 8MB +custom_meshtastic_has_ink_hud = true extends = esp32s3_base board = heltec_vision_master_e213 diff --git a/variants/esp32s3/heltec_vision_master_e290/platformio.ini b/variants/esp32s3/heltec_vision_master_e290/platformio.ini index 5affd24de..9fdb023de 100644 --- a/variants/esp32s3/heltec_vision_master_e290/platformio.ini +++ b/variants/esp32s3/heltec_vision_master_e290/platformio.ini @@ -10,6 +10,7 @@ custom_meshtastic_images = heltec-vision-master-e290.svg custom_meshtastic_tags = Heltec custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 8MB +custom_meshtastic_has_ink_hud = true extends = esp32s3_base board = heltec_vision_master_e290 diff --git a/variants/esp32s3/heltec_wireless_paper/platformio.ini b/variants/esp32s3/heltec_wireless_paper/platformio.ini index ce4bed30e..acd619c48 100644 --- a/variants/esp32s3/heltec_wireless_paper/platformio.ini +++ b/variants/esp32s3/heltec_wireless_paper/platformio.ini @@ -9,6 +9,7 @@ custom_meshtastic_display_name = Heltec Wireless Paper custom_meshtastic_images = heltec-wireless-paper.svg custom_meshtastic_tags = Heltec custom_meshtastic_partition_scheme = 8MB +custom_meshtastic_has_ink_hud = true extends = esp32s3_base board = heltec_wifi_lora_32_V3 diff --git a/variants/esp32s3/mesh-tab/platformio.ini b/variants/esp32s3/mesh-tab/platformio.ini index ecf5498b3..a153ba9fb 100644 --- a/variants/esp32s3/mesh-tab/platformio.ini +++ b/variants/esp32s3/mesh-tab/platformio.ini @@ -12,6 +12,7 @@ build_flags = ${esp32s3_base.build_flags} -D CONFIG_ARDUHAL_ESP_LOG -D CONFIG_ARDUHAL_LOG_COLORS=1 -D CONFIG_DISABLE_HAL_LOCKS=1 + -D MESHTASTIC_EXCLUDE_SCREEN=1 -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 -D MESHTASTIC_EXCLUDE_BLUETOOTH=1 @@ -31,7 +32,10 @@ build_flags = ${esp32s3_base.build_flags} -D HAS_SCREEN=0 -D HAS_TFT=1 -D USE_PIN_BUZZER - -D RAM_SIZE=1024 + -D MAP_TILES_GREY ; required for 2MB PSRAM + -D RAM_SIZE=1432 + -D STBI_ARENA_SIZE=450000 + -D LV_CACHE_DEF_SIZE=0 -D LGFX_DRIVER_TEMPLATE -D LGFX_DRIVER=LGFX_GENERIC -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" diff --git a/variants/esp32s3/mini-epaper-s3/platformio.ini b/variants/esp32s3/mini-epaper-s3/platformio.ini index 5c3e64681..3e4802319 100644 --- a/variants/esp32s3/mini-epaper-s3/platformio.ini +++ b/variants/esp32s3/mini-epaper-s3/platformio.ini @@ -1,5 +1,5 @@ [env:mini-epaper-s3] -;custom_meshtastic_hw_model = +custom_meshtastic_hw_model = 125 custom_meshtastic_hw_model_slug = MINI_EPAPER_S3 custom_meshtastic_architecture = esp32-s3 custom_meshtastic_actively_supported = true @@ -8,6 +8,7 @@ custom_meshtastic_display_name = LILYGO Mini ePaper S3 E-Ink custom_meshtastic_images = mini-epaper-s3.svg custom_meshtastic_tags = LilyGo custom_meshtastic_requires_dfu = no +custom_meshtastic_has_mui = false extends = esp32s3_base board = mini-epaper-s3 diff --git a/variants/esp32s3/picomputer-s3/platformio.ini b/variants/esp32s3/picomputer-s3/platformio.ini index 82147f222..6f218a126 100644 --- a/variants/esp32s3/picomputer-s3/platformio.ini +++ b/variants/esp32s3/picomputer-s3/platformio.ini @@ -6,6 +6,7 @@ custom_meshtastic_actively_supported = true custom_meshtastic_support_level = 3 custom_meshtastic_display_name = Pi Computer S3 custom_meshtastic_partition_scheme = 8MB +custom_meshtastic_has_mui = true extends = esp32s3_base board = bpi_picow_esp32_s3 diff --git a/variants/esp32s3/rak3312/platformio.ini b/variants/esp32s3/rak3312/platformio.ini index 113c2f527..87e5b63ff 100644 --- a/variants/esp32s3/rak3312/platformio.ini +++ b/variants/esp32s3/rak3312/platformio.ini @@ -9,6 +9,7 @@ custom_meshtastic_images = rak_3312.svg custom_meshtastic_tags = RAK custom_meshtastic_requires_dfu = false custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = false extends = esp32s3_base board = wiscore_rak3312 diff --git a/variants/esp32s3/rak_wismesh_tap_v2/platformio.ini b/variants/esp32s3/rak_wismesh_tap_v2/platformio.ini index 96b1a067b..7847410ae 100644 --- a/variants/esp32s3/rak_wismesh_tap_v2/platformio.ini +++ b/variants/esp32s3/rak_wismesh_tap_v2/platformio.ini @@ -20,6 +20,7 @@ custom_meshtastic_display_name = RAK WisMesh Tap V2 custom_meshtastic_images = rak-wismesh-tap-v2.svg custom_meshtastic_tags = RAK custom_meshtastic_partition_scheme = 8MB +custom_meshtastic_has_mui = true extends = esp32s3_base board = wiscore_rak3312 @@ -43,6 +44,7 @@ extends = env:rak_wismesh_tap_v2 build_flags = ${env:rak_wismesh_tap_v2.build_flags} + -D MESHTASTIC_EXCLUDE_WEBSERVER=1 -D CONFIG_ARDUHAL_ESP_LOG -D CONFIG_ARDUHAL_LOG_COLORS=1 -D CONFIG_DISABLE_HAL_LOCKS=1 diff --git a/variants/esp32s3/seeed-sensecap-indicator/platformio.ini b/variants/esp32s3/seeed-sensecap-indicator/platformio.ini index 37686fbc7..158e704ec 100644 --- a/variants/esp32s3/seeed-sensecap-indicator/platformio.ini +++ b/variants/esp32s3/seeed-sensecap-indicator/platformio.ini @@ -9,7 +9,7 @@ custom_meshtastic_display_name = Seeed SenseCAP Indicator custom_meshtastic_images = seeed-sensecap-indicator.svg custom_meshtastic_tags = Seeed custom_meshtastic_partition_scheme = 8MB - = true +custom_meshtastic_has_mui = true extends = esp32s3_base platform_packages = diff --git a/variants/esp32s3/t-beam-1w/platformio.ini b/variants/esp32s3/t-beam-1w/platformio.ini index 9abf895db..b14f2fe3c 100644 --- a/variants/esp32s3/t-beam-1w/platformio.ini +++ b/variants/esp32s3/t-beam-1w/platformio.ini @@ -8,6 +8,7 @@ custom_meshtastic_support_level = 1 custom_meshtastic_display_name = LILYGO T-Beam 1W custom_meshtastic_images = tbeam-1w.svg custom_meshtastic_tags = LilyGo +custom_meshtastic_has_mui = false extends = esp32s3_base board = t-beam-1w diff --git a/variants/esp32s3/t-deck-pro/platformio.ini b/variants/esp32s3/t-deck-pro/platformio.ini index c5411da13..93ef8babf 100644 --- a/variants/esp32s3/t-deck-pro/platformio.ini +++ b/variants/esp32s3/t-deck-pro/platformio.ini @@ -9,6 +9,7 @@ custom_meshtastic_images = tdeck_pro.svg custom_meshtastic_tags = LilyGo custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = false extends = esp32s3_base board = t-deck-pro diff --git a/variants/esp32s3/t-deck/platformio.ini b/variants/esp32s3/t-deck/platformio.ini index 7d79e934c..1b3599464 100644 --- a/variants/esp32s3/t-deck/platformio.ini +++ b/variants/esp32s3/t-deck/platformio.ini @@ -10,6 +10,7 @@ custom_meshtastic_images = t-deck.svg custom_meshtastic_tags = LilyGo custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = true extends = esp32s3_base board = t-deck diff --git a/variants/esp32s3/t5s3_epaper/platformio.ini b/variants/esp32s3/t5s3_epaper/platformio.ini index 8f4a02a00..bad36706c 100644 --- a/variants/esp32s3/t5s3_epaper/platformio.ini +++ b/variants/esp32s3/t5s3_epaper/platformio.ini @@ -30,6 +30,8 @@ lib_deps = [env:t5s3_epaper_inkhud] extends = t5s3_epaper_base, inkhud +board_level = extra # inkhud port is incomplete +board_check = false build_flags = ${t5s3_epaper_base.build_flags} ${inkhud.build_flags} diff --git a/variants/esp32s3/tlora-pager/platformio.ini b/variants/esp32s3/tlora-pager/platformio.ini index dc96113b0..832f9d7d7 100644 --- a/variants/esp32s3/tlora-pager/platformio.ini +++ b/variants/esp32s3/tlora-pager/platformio.ini @@ -10,6 +10,7 @@ custom_meshtastic_images = lilygo-tlora-pager.svg custom_meshtastic_tags = LilyGo custom_meshtastic_requires_dfu = true custom_meshtastic_partition_scheme = 16MB +custom_meshtastic_has_mui = true extends = esp32s3_base board = t-deck-pro ; same as T-Deck Pro diff --git a/variants/esp32s3/tlora_t3s3_epaper/platformio.ini b/variants/esp32s3/tlora_t3s3_epaper/platformio.ini index f9d1ea7db..8f764bbe6 100644 --- a/variants/esp32s3/tlora_t3s3_epaper/platformio.ini +++ b/variants/esp32s3/tlora_t3s3_epaper/platformio.ini @@ -8,6 +8,7 @@ custom_meshtastic_display_name = LILYGO T-LoRa T3-S3 E-Ink custom_meshtastic_images = tlora-t3s3-epaper.svg custom_meshtastic_tags = LilyGo custom_meshtastic_requires_dfu = true +custom_meshtastic_has_ink_hud = true extends = esp32s3_base board = tlora-t3s3-v1 diff --git a/variants/nrf52840/ELECROW-ThinkNode-M1/platformio.ini b/variants/nrf52840/ELECROW-ThinkNode-M1/platformio.ini index 2a6cea73e..c169de8f7 100644 --- a/variants/nrf52840/ELECROW-ThinkNode-M1/platformio.ini +++ b/variants/nrf52840/ELECROW-ThinkNode-M1/platformio.ini @@ -8,6 +8,7 @@ custom_meshtastic_support_level = 1 custom_meshtastic_display_name = ThinkNode M1 custom_meshtastic_images = thinknode_m1.svg custom_meshtastic_tags = Elecrow +custom_meshtastic_has_ink_hud = true extends = nrf52840_base board = ThinkNode-M1 diff --git a/variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h b/variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h index 71508c037..ac7ef57c4 100644 --- a/variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h +++ b/variants/nrf52840/diy/nrf52_promicro_diy_tcxo/rfswitch.h @@ -12,9 +12,15 @@ static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11 RADIOLIB_NC}; static const Module::RfSwitchMode_t rfswitch_table[] = { - // mode DIO5 DIO6 DIO7 - {LR11x0::MODE_STBY, {LOW, LOW, LOW}}, {LR11x0::MODE_RX, {LOW, HIGH, LOW}}, - {LR11x0::MODE_TX, {HIGH, HIGH, LOW}}, {LR11x0::MODE_TX_HP, {HIGH, LOW, LOW}}, - {LR11x0::MODE_TX_HF, {LOW, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, HIGH}}, - {LR11x0::MODE_WIFI, {LOW, LOW, LOW}}, END_OF_MODE_TABLE, + // clang-format off + // mode DIO5 DIO6 DIO7 + {LR11x0::MODE_STBY, {LOW, LOW, LOW}}, + {LR11x0::MODE_RX, {LOW, HIGH, LOW}}, + {LR11x0::MODE_TX, {HIGH, HIGH, LOW}}, + {LR11x0::MODE_TX_HP, {HIGH, LOW, LOW}}, + {LR11x0::MODE_TX_HF, {LOW, LOW, LOW}}, + {LR11x0::MODE_GNSS, {LOW, LOW, HIGH}}, + {LR11x0::MODE_WIFI, {LOW, LOW, LOW}}, + END_OF_MODE_TABLE, + // clang-format on }; diff --git a/variants/nrf52840/heltec_mesh_pocket/platformio.ini b/variants/nrf52840/heltec_mesh_pocket/platformio.ini index 9fbcc890d..c9b599382 100644 --- a/variants/nrf52840/heltec_mesh_pocket/platformio.ini +++ b/variants/nrf52840/heltec_mesh_pocket/platformio.ini @@ -15,6 +15,7 @@ custom_meshtastic_display_name = Heltec Mesh Pocket custom_meshtastic_actively_supported = true custom_meshtastic_variant = 5000mAh custom_meshtastic_key = heltec_mesh_pocket +custom_meshtastic_has_ink_hud = true # add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling. build_flags = ${nrf52840_base.build_flags} @@ -78,6 +79,7 @@ custom_meshtastic_display_name = Heltec Mesh Pocket custom_meshtastic_actively_supported = true custom_meshtastic_variant = 10000mAh custom_meshtastic_key = heltec_mesh_pocket +custom_meshtastic_has_ink_hud = true # add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling. build_flags = ${nrf52840_base.build_flags} diff --git a/variants/nrf52840/seeed_wio_tracker_L1_eink/platformio.ini b/variants/nrf52840/seeed_wio_tracker_L1_eink/platformio.ini index d8fbaf8ff..26f4de565 100644 --- a/variants/nrf52840/seeed_wio_tracker_L1_eink/platformio.ini +++ b/variants/nrf52840/seeed_wio_tracker_L1_eink/platformio.ini @@ -7,6 +7,7 @@ custom_meshtastic_support_level = 1 custom_meshtastic_display_name = Seeed Wio Tracker L1 E-Ink custom_meshtastic_images = wio_tracker_l1_eink.svg custom_meshtastic_tags = Seeed +custom_meshtastic_has_ink_hud = true board = seeed_wio_tracker_L1 extends = nrf52840_base diff --git a/variants/nrf52840/t-echo-plus/platformio.ini b/variants/nrf52840/t-echo-plus/platformio.ini index 9ec9187e8..313eceadc 100644 --- a/variants/nrf52840/t-echo-plus/platformio.ini +++ b/variants/nrf52840/t-echo-plus/platformio.ini @@ -1,4 +1,15 @@ [env:t-echo-plus] +custom_meshtastic_hw_model = 33 +custom_meshtastic_hw_model_slug = T_ECHO_PLUS +custom_meshtastic_architecture = nrf52840 +custom_meshtastic_actively_supported = true +custom_meshtastic_support_level = 1 +custom_meshtastic_display_name = LILYGO T-Echo Plus +custom_meshtastic_images = t-echo_plus.svg +custom_meshtastic_tags = LilyGo +custom_meshtastic_requires_dfu = true +custom_meshtastic_has_ink_hud = true + extends = nrf52840_base board = t-echo board_level = pr diff --git a/variants/nrf52840/t-echo/platformio.ini b/variants/nrf52840/t-echo/platformio.ini index 89ce488ad..58ad029ae 100644 --- a/variants/nrf52840/t-echo/platformio.ini +++ b/variants/nrf52840/t-echo/platformio.ini @@ -8,6 +8,7 @@ custom_meshtastic_support_level = 1 custom_meshtastic_display_name = LILYGO T-Echo custom_meshtastic_images = t-echo.svg custom_meshtastic_tags = LilyGo +custom_meshtastic_has_ink_hud = true extends = nrf52840_base board = t-echo diff --git a/variants/nrf52840/wio-sdk-wm1110/platformio.ini b/variants/nrf52840/wio-sdk-wm1110/platformio.ini index 7c11ef6f6..9fac82289 100644 --- a/variants/nrf52840/wio-sdk-wm1110/platformio.ini +++ b/variants/nrf52840/wio-sdk-wm1110/platformio.ini @@ -9,6 +9,7 @@ extra_scripts = # Remove adafruit USB serial from the build (it is incompatible with using the ch340 serial chip on this board) build_unflags = + ${nrf52840_base.build_unflags} -Ofast -Og -ggdb3 diff --git a/version.properties b/version.properties index c25179ae2..8621dd9c9 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 7 -build = 21 +build = 22