Merge branch 'develop' into pioarduino

This commit is contained in:
Manuel
2026-04-09 17:02:38 +02:00
committed by GitHub
80 changed files with 1423 additions and 311 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]

View File

@@ -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]

View File

@@ -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

View File

@@ -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)

View File

@@ -87,6 +87,9 @@
</screenshots>
<releases>
<release version="2.7.22" date="2026-04-06">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.22</url>
</release>
<release version="2.7.21" date="2026-03-11">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.21</url>
</release>

29
boards/ttgo-tbeam.json Normal file
View File

@@ -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"
}

6
debian/changelog vendored
View File

@@ -1,3 +1,9 @@
meshtasticd (2.7.22.0) unstable; urgency=medium
* Version 2.7.22
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Mon, 06 Apr 2026 11:34:12 +0000
meshtasticd (2.7.21.0) unstable; urgency=medium
* Version 2.7.21

View File

@@ -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]

View File

@@ -4,6 +4,7 @@
":dependencyDashboard",
":semanticCommitTypeAll(chore)",
":ignoreModulesAndTests",
":noUnscheduledUpdates",
"schedule:daily",
"group:recommended",
"replacements:all",

View File

@@ -231,7 +231,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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 <http://www.gnu.org/licenses/>.
#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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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)

View File

@@ -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 920925 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

View File

@@ -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)

View File

@@ -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

View File

@@ -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.
------------------------------------------------------------------------------------------------------------------------------------------ */

View File

@@ -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. */

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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(<Adafruit_SHT31.h>)
#include "Sensor/SHT31Sensor.h"
#endif
#if __has_include(<Adafruit_LPS2X.h>)
#include "Sensor/LPS22HBSensor.h"
#endif
#if __has_include(<Adafruit_SHTC3.h>)
#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(<Adafruit_SHT4x.h>)
#include "Sensor/SHT4XSensor.h"
#if __has_include(<SHTSensor.h>)
#include "Sensor/SHTXXSensor.h"
#endif
#if __has_include(<SparkFun_MLX90632_Arduino_Library.h>)
@@ -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(<Adafruit_MCP9808.h>)
addSensor<MCP9808Sensor>(i2cScanner, ScanI2C::DeviceType::MCP9808);
#endif
#if __has_include(<Adafruit_SHT31.h>)
addSensor<SHT31Sensor>(i2cScanner, ScanI2C::DeviceType::SHT31);
#endif
#if __has_include(<Adafruit_LPS2X.h>)
addSensor<LPS22HBSensor>(i2cScanner, ScanI2C::DeviceType::LPS22HB);
#endif
#if __has_include(<Adafruit_SHTC3.h>)
addSensor<SHTC3Sensor>(i2cScanner, ScanI2C::DeviceType::SHTC3);
#endif
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
addSensor<RAK12035Sensor>(i2cScanner, ScanI2C::DeviceType::RAK12035);
#endif
@@ -223,13 +218,9 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
#if __has_include(<ClosedCube_OPT3001.h>)
addSensor<OPT3001Sensor>(i2cScanner, ScanI2C::DeviceType::OPT3001);
#endif
#if __has_include(<Adafruit_SHT4x.h>)
addSensor<SHT4XSensor>(i2cScanner, ScanI2C::DeviceType::SHT4X);
#endif
#if __has_include(<SparkFun_MLX90632_Arduino_Library.h>)
addSensor<MLX90632Sensor>(i2cScanner, ScanI2C::DeviceType::MLX90632);
#endif
#if __has_include(<Adafruit_BMP3XX.h>)
addSensor<BMP3XXSensor>(i2cScanner, ScanI2C::DeviceType::BMP_3XX);
#endif
@@ -245,7 +236,10 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
#if __has_include(<BH1750_WE.h>)
addSensor<BH1750Sensor>(i2cScanner, ScanI2C::DeviceType::BH1750);
#endif
#if __has_include(<SHTSensor.h>)
// TODO Can we scan for multiple sensors connected on the same bus?
addSensor<SHTXXSensor>(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)) {

View File

@@ -1,31 +0,0 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_SHT31.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "SHT31Sensor.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHT31.h>
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

View File

@@ -1,20 +0,0 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_SHT31.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHT31.h>
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

View File

@@ -1,48 +0,0 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_SHT4x.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "SHT4XSensor.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHT4x.h>
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

View File

@@ -1,20 +0,0 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_SHT4x.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHT4x.h>
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

View File

@@ -1,35 +0,0 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_SHTC3.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "SHTC3Sensor.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHTC3.h>
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

View File

@@ -1,20 +0,0 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_SHTC3.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHTC3.h>
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

View File

@@ -0,0 +1,145 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<SHTSensor.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "SHTXXSensor.h"
#include "TelemetrySensor.h"
#include <SHTSensor.h>
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

View File

@@ -0,0 +1,29 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<SHTSensor.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <SHTSensor.h>
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

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +1,6 @@
#include "RTC.h"
#include "configuration.h"
#include <stdarg.h>
#include <stm32wle5xx.h>
#include <stm32wlxx_hal.h>
@@ -53,4 +54,99 @@ extern "C" void __wrap__tzset_unlocked_r(struct _reent *reent_ptr)
{
return;
}
#endif
#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();
}
}

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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 =

View File

@@ -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 =

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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\"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 =

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
};

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 7
build = 21
build = 22