Compare commits

...
24 Commits
Author SHA1 Message Date
2482306697 Upgrade trunk (#10772)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-06-24 08:00:16 -05:00
217ada19ba Automated version bumps (#10773)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-06-24 08:00:05 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
e3145f9007 Update actions/cache action to v6 (#10771)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-23 20:41:42 -05:00
54e0d8d0ab fix(phone-api): skip manifest scan for node-info-only config requests (#10754)
* fix(fs): bound getFiles() result size and harden traversal

The recursive filesystem traversal in getFiles() could grow its result
vector without limit, contributing to heap pressure on memory-constrained
devices during client config starts. The implementation also relied on
unbounded strcpy and per-entry String() allocations for dot-suffix
filtering, and leaked the directory handle when the opened path was not
a directory.

Rework the traversal to address all of those at once:

- Add optional maxCount (default 64) and wasLimited out-param. The walk
  stops once maxCount entries have been collected and wasLimited is set,
  so callers can distinguish a complete listing from a truncated one.
  Default arguments preserve backward compatibility for existing callers.

- Extract the recursive walk into a collectFiles() helper in an
  anonymous namespace, accumulating into a single caller-owned vector
  instead of building and inserting temporary vectors at every recursion
  level.

- Replace strcpy with strlcpy so file_name writes are bounded by the
  destination buffer.

- Replace String(name).endsWith(".") with a stack-based
  pathEndsWithDot() helper to avoid a heap allocation per entry.

- Close the directory handle when the opened path is not a directory,
  and close the file in both branches of recursion instead of only the
  leaf branch (the previous code leaked the handle when depth was
  exhausted).

- Compile-gate the std::bad_alloc reserve probe-down behind
  __cpp_exceptions / __EXCEPTIONS so the fallback only compiles where
  bad_alloc is actually catchable. No-exception targets (nRF52, RP2040,
  STM32, ESP32-C6) skip the probe and rely on the bounded maxCount
  alone, which is safe because the default cap is small enough to fit
  comfortably in available RAM on every supported platform.

* fix(phone-api): skip manifest scan for node-info-only config requests

A client can request a node-info-only config response by sending
want_config_id with the SPECIAL_NONCE_ONLY_NODES nonce. The manifest
walk in handleStartConfig() ran unconditionally even though
STATE_SEND_FILEMANIFEST short-circuits past the manifest on that path,
so the SPI lock and recursive filesystem traversal were wasted work.
On memory-constrained devices this extra heap pressure was enough to
trigger allocation aborts and spontaneous reboots before the node-info
response could complete.

Gate the manifest call behind config_nonce != SPECIAL_NONCE_ONLY_NODES
so the node-info-only path no longer touches the filesystem at all, and
release any stale manifest storage left over from a previous run.

For normal full-config requests, also tighten the scan limits from
depth 10 / unbounded to depth 3 / max 64 entries via the new getFiles()
parameters. A 10-level recursive listing was never useful for a client
file picker and amplified heap pressure for no benefit. Log a warning
when the listing was truncated so operators can distinguish a bounded
result from a genuinely empty filesystem.

A few small cleanups fall out of the above:

- Replace raw spiLock->lock()/unlock() with a LockGuard so the lock is
  released even if getFiles() throws on exception-enabled targets.

- Use a releaseFilesManifest() helper (swap-with-empty idiom) in
  close() and the STATE_SEND_FILEMANIFEST drain path instead of the
  previous clear()+shrink_to_fit() pair. Equivalent behavior, but the
  swap idiom is the canonical vector-freeing pattern and centralizing
  it avoids divergence between call sites.

- Use %zu for the size_t log arguments.

* fix(fs): harden bounded directory traversal

Close each child directory entry before recursive descent so bounded manifest scans do not stack file handles on constrained filesystems.

Treat null or overlong paths as truncated listings, handle reserve length failures like allocation failures, and keep manifest constants aligned with repository naming.

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-23 11:26:52 -05:00
640002dc93 Upgrade trunk (#10763)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-06-23 06:32:17 -05:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Ben Meadors
e4c1374b99 fix(FSCommon): add nRF52 LittleFS empty-name guard to getFiles() (#10757)
* Initial plan

* fix(FSCommon): add file.name()[0] guard in getFiles() for nRF52 LittleFS bug workaround

* style(FSCommon): run clang-format (trunk fmt)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-06-23 06:23:53 -05:00
Ben Meadors 22d08b4303 Fix build on picomputer 2026-06-23 06:03:37 -05:00
560515f014 Upgrade trunk (#10760)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-06-22 06:22:04 -05:00
ManuelGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
4044f4af6c tdeck touch driver fix (#10740)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-20 13:15:11 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3b20601697 Update meshtastic/device-ui digest to 1c45ebc (#10749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-19 19:56:04 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
a9a88e7ac7 Update platform-native digest to 61067ac (#10750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-19 19:55:49 -05:00
Jonathan BennettandGitHub 20c9e154dd enable Adafruit SHTC3 library on native (#10747) 2026-06-19 12:52:10 -05:00
e08b67aa8c Upgrade trunk (#10738)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-06-19 06:18:41 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
df3d5bb344 Update actions/checkout action to v7 (#10744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-19 06:18:09 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
804ec0fb1b Update meshtastic/device-ui digest to 6cadf54 (#10743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-19 06:17:41 -05:00
8975181bd0 fix(esp32): skip RTC timer wake on user shutdown; TAP V2 OCV and partition (#10739)
* fix(esp32): skip RTC timer wake on user shutdown

Do not arm esp_sleep_enable_timer_wakeup when msecToWake is portMAX_DELAY (UI shutdown), matching nRF52 system_off semantics.

fix(rak_wismesh_tap_v2): Tag OCV curve and 16MB partition

Add OCV_ARRAY matching WisMesh Tag for accurate SOC. Use 16MB flash partition scheme for TAP V2 hardware.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Trunkt

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-06-18 16:30:41 -05:00
Jonathan BennettandGitHub 1003d154b2 Update OCV_ARRAY values in Thinknode m5 variant.h 2026-06-17 22:16:09 -05:00
Jonathan BennettandGitHub 8ba9d0d15f Set the time from GPS every 30 minutes (#10737) 2026-06-17 18:46:58 -05:00
ca1304e6da Upgrade trunk (#10720)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-06-17 05:54:26 -05:00
Jonathan BennettandGitHub 40adf3a0d0 Beta fixes (#10728)
* Wipe message Store on factory reset

* Check for destination 0 in a new message, and convert to broadcast

* Make sure CHARGE_LED_state gets turned off, to avoid stuck LEDs

* Take the spiLock in MessageStore when clearing messages

* Trunk

* Add thinknode M5 voltage curve

* Fix the oops
2026-06-16 22:37:14 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
ac25b85f5b Update meshtastic/device-ui digest to 4ec010c (#10732)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-16 20:21:11 -05:00
a49729eb89 Additional *RAK* missing values for 6421 / 13300 13302 modules + Zebra/Nebra Hat Configs (#10644)
* rebased to master

* Update bin/config.d/lora-ZebraHat_2W.yaml

Co-authored-by: Austin <vidplace7@gmail.com>

* Update bin/config.d/lora-ZebraHat_1W.yaml

Co-authored-by: Austin <vidplace7@gmail.com>

* Update bin/config.d/lora-NebraHat_2W.yaml

Co-authored-by: Austin <vidplace7@gmail.com>

* Update bin/config.d/lora-NebraHat_1W.yaml

Co-authored-by: Austin <vidplace7@gmail.com>

* Remove TX_GAIN_LORA configuration line

* Remove TX_GAIN_LORA configuration line

* Comment out TX_GAIN_LORA configuration

* Comment out TX_GAIN_LORA configuration

* Update lora-ok3506-RAK6421-13300-slot1.yaml

* Update lora-ok3506-RAK6421-13300-slot2.yaml

* Update lora-RAK6421-13300-slot1.yaml

* Update lora-RAK6421-13300-slot2.yaml

---------

Co-authored-by: Austin <vidplace7@gmail.com>
2026-06-16 11:22:45 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
6e02b9aed9 Update Sensirion I2C SCD30 to v1.1.1 (#10294)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-14 07:08:28 -05:00
9972feb5bb Lora led rx (#10674)
* add optional LED_LORA to indicate LoRa TX

* Briefly flash LED_LORA on packet RX

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-06-13 12:06:06 -05:00
63 changed files with 392 additions and 103 deletions
+1 -1
View File
@@ -76,7 +76,7 @@ runs:
done
- name: PlatformIO ${{ inputs.arch }} download cache
uses: actions/cache@v5
uses: actions/cache@v6
with:
path: ~/.platformio/.cache
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
+1 -1
View File
@@ -5,7 +5,7 @@ runs:
using: composite
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
path: meshtasticd
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
outputs:
artifact-id: ${{ steps.upload-firmware.outputs.artifact-id }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
submodules: recursive
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
runs-on: macos-${{ inputs.macos_ver }}
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
+3 -3
View File
@@ -43,7 +43,7 @@ jobs:
- stm32
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: 3.x
@@ -64,7 +64,7 @@ jobs:
if: ${{ inputs.target != '' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
@@ -93,7 +93,7 @@ jobs:
needs: [version, build]
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
runs-on: ${{ inputs.runs-on }}
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
+1 -1
View File
@@ -103,7 +103,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
+7 -7
View File
@@ -40,7 +40,7 @@ jobs:
- check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: 3.x
@@ -64,7 +64,7 @@ jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
@@ -86,7 +86,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
submodules: recursive
- name: Check ${{ matrix.check.board }}
@@ -189,7 +189,7 @@ jobs:
needs: [version, build]
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
@@ -261,7 +261,7 @@ jobs:
# - MacOS
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -362,7 +362,7 @@ jobs:
needs: [release-artifacts, version]
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Setup Python
uses: actions/setup-python@v6
@@ -417,7 +417,7 @@ jobs:
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
+2 -2
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Trunk Check
uses: trunk-io/trunk-action@v1.3.1
@@ -31,7 +31,7 @@ jobs:
pull-requests: write # For trunk to create PRs
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Trunk Upgrade
uses: trunk-io/trunk-action/upgrade@v1.3.1
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
needs: build-debian-src
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
path: meshtasticd
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
needs: build-debian-src
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: recursive
path: meshtasticd
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
checks: write
pull-requests: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
submodules: recursive
+1 -1
View File
@@ -91,7 +91,7 @@ jobs:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
# Always use master branch for version bumps
ref: master
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v6
uses: actions/checkout@v7
# step 2
- name: full scan
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
+3 -3
View File
@@ -14,7 +14,7 @@ jobs:
name: Native Simulator Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
submodules: recursive
@@ -68,7 +68,7 @@ jobs:
name: Native PlatformIO Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
submodules: recursive
@@ -123,7 +123,7 @@ jobs:
- platformio-tests
if: always()
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: test-runner
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
# - uses: actions/setup-python@v6
# with:
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Trunk Check
uses: trunk-io/trunk-action@v1.3.1
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Trunk Check
uses: trunk-io/trunk-action@v1.3.1
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
submodules: true
+6 -6
View File
@@ -8,17 +8,17 @@ plugins:
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- checkov@3.3.1
- renovate@43.220.0
- checkov@3.3.2
- renovate@43.242.0
- prettier@3.8.4
- trufflehog@3.95.5
- trufflehog@3.95.6
- yamllint@1.38.0
- bandit@1.9.4
- trivy@0.71.0
- trivy@0.71.2
- taplo@0.10.0
- ruff@0.15.17
- ruff@0.15.19
- isort@8.0.1
- markdownlint@0.48.0
- markdownlint@0.49.0
- oxipng@10.1.1
- svgo@4.0.1
- actionlint@1.7.12
+19
View File
@@ -0,0 +1,19 @@
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/NebraHat
# Use for 1 watt hat
Meta:
name: NebraHat 1W
support: community
compatible:
- raspberry-pi
Lora:
Module: sx1262 # Nebra SX1262 Pi Hat - 1W
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
# CS: 8 # Newer version of MeshtasticD do not need this? If issues uncomment this line
IRQ: 22
Busy: 4
Reset: 18
RXen: 25
I2C:
I2CDevice: /dev/i2c-1
+20
View File
@@ -0,0 +1,20 @@
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/NebraHat
# Use for 2 watt hat
Meta:
name: NebraHat 2W
support: community
compatible:
- raspberry-pi
Lora:
Module: sx1262 # Nebra SX1262 Pi Hat - 2W
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
SX126X_MAX_POWER: 8
# CS: 8 # Newer version of MeshtasticD do not need this? If issues uncomment this line
IRQ: 22
Busy: 4
Reset: 18
RXen: 25
I2C:
I2CDevice: /dev/i2c-1
+1 -1
View File
@@ -18,4 +18,4 @@ Lora:
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.0
# CS: 8
# CS: 8
+1 -1
View File
@@ -18,4 +18,4 @@ Lora:
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: 7
# CS: 7
+19
View File
@@ -0,0 +1,19 @@
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/ZebraHAT
# Use for 1 watt hat
Meta:
name: ZebraHat 1W
support: community
compatible:
- raspberry-pi
Lora:
Module: sx1262 # Zebra SX1262 Pi Hat - 1W
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
SX126X_MAX_POWER: 18
CS: 24
IRQ: 22
Busy: 27
Reset: 17
I2C:
I2CDevice: /dev/i2c-1
+20
View File
@@ -0,0 +1,20 @@
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/ZebraHAT
# Use for 2 watt hat
Meta:
name: ZebraHat 2W
support: community
compatible:
- raspberry-pi
Lora:
Module: sx1262 # Zebra SX1262 Pi Hat - 2W
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
SX126X_MAX_POWER: 8
CS: 24
IRQ: 22
Busy: 27
Reset: 17
RXen: 25
I2C:
I2CDevice: /dev/i2c-1
@@ -29,6 +29,8 @@ Lora:
- pin: 50 # GPIO1_C2 (physical 16)
gpiochip: 1
line: 18
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
# pin: 7
@@ -29,6 +29,8 @@ Lora:
- pin: 50 # GPIO1_C2 (physical 16)
gpiochip: 1
line: 18
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
# pin: 7
@@ -29,6 +29,8 @@ Lora:
- pin: 13 # GPIO0_B5
gpiochip: 0
line: 13
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: # GPIO0_B1
# pin: 9
@@ -29,6 +29,8 @@ Lora:
- pin: 13 # GPIO0_B5
gpiochip: 0
line: 13
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: # GPIO0_B1
# pin: 9
@@ -31,6 +31,8 @@ Lora:
- pin: 103 # GPIO3_A7 (physical 16)
gpiochip: 3
line: 7
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
# pin: 15
@@ -31,6 +31,8 @@ Lora:
- pin: 103 # GPIO3_A7 (physical 16)
gpiochip: 3
line: 7
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.1
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
# pin: 15
+2
View File
@@ -1,3 +1,5 @@
# This config works with all revisions of the Meshtoad USB radio.
Meta:
name: meshtoad-e22
support: official
@@ -87,6 +87,9 @@
</screenshots>
<releases>
<release version="2.7.27" date="2026-06-24">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.27</url>
</release>
<release version="2.7.26" date="2026-06-10">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.26</url>
</release>
+6
View File
@@ -1,3 +1,9 @@
meshtasticd (2.7.27.0) unstable; urgency=medium
* Version 2.7.27
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 24 Jun 2026 11:20:05 +0000
meshtasticd (2.7.26.0) unstable; urgency=medium
* Version 2.7.26
+4 -4
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/502ba30dbccc6a323f1d4f7ca961131c27f60672.zip
https://github.com/meshtastic/device-ui/archive/1c45ebc7433acb8ba3fe96a6f7deca9c43fa54cf.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
@@ -199,6 +199,8 @@ lib_deps =
https://github.com/adafruit/Adafruit_TSL2561/archive/refs/tags/1.1.3.zip
# renovate: datasource=github-tags depName=BH1750_WE packageName=wollewald/BH1750_WE
https://github.com/wollewald/BH1750_WE/archive/refs/tags/1.1.10.zip
# renovate: datasource=github-tags depName=Adafruit SHTC3 packageName=adafruit/Adafruit_SHTC3
https://github.com/adafruit/Adafruit_SHTC3/archive/refs/tags/1.0.2.zip
; Common environmental sensor libraries (not included in native / portduino)
[environmental_extra_common]
@@ -207,8 +209,6 @@ lib_deps =
https://github.com/adafruit/Adafruit_BMP3XX/archive/refs/tags/2.1.6.zip
# renovate: datasource=github-tags depName=Adafruit MAX1704X packageName=adafruit/Adafruit_MAX1704X
https://github.com/adafruit/Adafruit_MAX1704X/archive/refs/tags/1.0.3.zip
# renovate: datasource=github-tags depName=Adafruit SHTC3 packageName=adafruit/Adafruit_SHTC3
https://github.com/adafruit/Adafruit_SHTC3/archive/refs/tags/1.0.2.zip
# renovate: datasource=github-tags depName=Adafruit LPS2X packageName=adafruit/Adafruit_LPS2X
https://github.com/adafruit/Adafruit_LPS2X/archive/refs/tags/2.0.6.zip
# renovate: datasource=github-tags depName=Adafruit SHT31 packageName=adafruit/Adafruit_SHT31
@@ -230,7 +230,7 @@ lib_deps =
# renovate: datasource=github-tags depName=Sensirion I2C SFA3x packageName=sensirion/arduino-i2c-sfa3x
https://github.com/Sensirion/arduino-i2c-sfa3x/archive/refs/tags/1.0.0.zip
# renovate: datasource=github-tags depName=Sensirion I2C SCD30 packageName=sensirion/arduino-i2c-scd30
https://github.com/Sensirion/arduino-i2c-scd30/archive/refs/tags/1.0.0.zip
https://github.com/Sensirion/arduino-i2c-scd30/archive/1.1.1.zip
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
[environmental_extra]
+101 -27
View File
@@ -99,48 +99,87 @@ bool renameFile(const char *pathFrom, const char *pathTo)
#endif
}
#include <cstring>
#include <new>
#include <stdexcept>
#include <vector>
/**
* @brief Get the list of files in a directory.
*
* This function returns a list of files in a directory. The list includes the full path of each file.
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
*
* @param dirname The name of the directory.
* @param levels The number of levels of subdirectories to list.
* @return A vector of strings containing the full path of each file in the directory.
*/
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
{
std::vector<meshtastic_FileInfo> filenames = {};
#ifdef FSCom
namespace
{
bool pathEndsWithDot(const char *path)
{
if (!path)
return false;
size_t length = strlen(path);
return length > 0 && path[length - 1] == '.';
}
bool copyFilePath(char *dest, size_t destSize, const char *path, bool *wasLimited)
{
if (!path || destSize == 0) {
if (wasLimited)
*wasLimited = true;
return false;
}
if (strlcpy(dest, path, destSize) >= destSize) {
if (wasLimited)
*wasLimited = true;
return false;
}
return true;
}
void collectFiles(const char *dirname, uint8_t levels, size_t maxCount, std::vector<meshtastic_FileInfo> &filenames,
bool *wasLimited)
{
if (!dirname)
return;
File root = FSCom.open(dirname, FILE_O_READ);
if (!root)
return filenames;
if (!root.isDirectory())
return filenames;
return;
if (!root.isDirectory()) {
root.close();
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
if (levels) {
// file.name()[0] check is a workaround for a bug in the Adafruit LittleFS nrf52 glue (see issue 4395)
while (file && file.name()[0]) {
if (filenames.size() >= maxCount) {
if (wasLimited)
*wasLimited = true;
file.close();
break;
}
const char *fileName = file.name();
if (file.isDirectory() && !pathEndsWithDot(fileName)) {
char pathBuffer[sizeof(((meshtastic_FileInfo *)nullptr)->file_name)] = {};
#ifdef ARCH_ESP32
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(file.path(), levels - 1);
const char *subDirPath = file.path();
#else
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(file.name(), levels - 1);
const char *subDirPath = fileName;
#endif
filenames.insert(filenames.end(), subDirFilenames.begin(), subDirFilenames.end());
file.close();
bool hasSubDirPath = copyFilePath(pathBuffer, sizeof(pathBuffer), subDirPath, wasLimited);
file.close();
if (levels && hasSubDirPath) {
collectFiles(pathBuffer, levels - 1, maxCount, filenames, wasLimited);
} else if (wasLimited) {
*wasLimited = true;
}
} else {
meshtastic_FileInfo fileInfo = {"", static_cast<uint32_t>(file.size())};
#ifdef ARCH_ESP32
strcpy(fileInfo.file_name, file.path());
bool hasFilePath = copyFilePath(fileInfo.file_name, sizeof(fileInfo.file_name), file.path(), wasLimited);
#else
strcpy(fileInfo.file_name, file.name());
bool hasFilePath = copyFilePath(fileInfo.file_name, sizeof(fileInfo.file_name), file.name(), wasLimited);
#endif
if (!String(fileInfo.file_name).endsWith(".")) {
if (hasFilePath && !pathEndsWithDot(fileInfo.file_name)) {
filenames.push_back(fileInfo);
}
file.close();
@@ -148,6 +187,41 @@ std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
file = root.openNextFile();
}
root.close();
}
} // namespace
#endif
// Callers must hold the SPI lock; recursion prevents taking it here.
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels, size_t maxCount, bool *wasLimited)
{
std::vector<meshtastic_FileInfo> filenames = {};
if (wasLimited)
*wasLimited = false;
#ifdef FSCom
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
size_t reservedCount = maxCount;
while (reservedCount > 0) {
try {
filenames.reserve(reservedCount);
break;
} catch (const std::bad_alloc &) {
reservedCount /= 2;
} catch (const std::length_error &) {
reservedCount /= 2;
}
}
if (reservedCount == 0) {
if (wasLimited)
*wasLimited = true;
return filenames;
}
if (reservedCount < maxCount) {
if (wasLimited)
*wasLimited = true;
maxCount = reservedCount;
}
#endif
collectFiles(dirname, levels, maxCount, filenames, wasLimited);
#endif
return filenames;
}
@@ -335,4 +409,4 @@ void setupSDCard()
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
#endif
}
}
+2 -2
View File
@@ -52,7 +52,7 @@ void fsInit();
void fsListFiles();
bool copyFile(const char *from, const char *to);
bool renameFile(const char *pathFrom, const char *pathTo);
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels, size_t maxCount = 64, bool *wasLimited = nullptr);
void listDir(const char *dirname, uint8_t levels, bool del = false);
void rmDir(const char *dirname);
void setupSDCard();
void setupSDCard();
+1
View File
@@ -360,6 +360,7 @@ void MessageStore::clearAllMessages()
resetMessagePool();
#ifdef FSCom
concurrency::LockGuard guard(spiLock);
SafeFile f(filename.c_str(), false);
uint8_t count = 0;
f.write(&count, 1); // write "0 messages"
+5 -3
View File
@@ -832,7 +832,10 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
switch (newState) {
case GPS_ACTIVE:
case GPS_IDLE:
if (oldState == GPS_ACTIVE || oldState == GPS_IDLE) // If hardware already awake, no changes needed
if (oldState == GPS_ACTIVE)
break;
gotTime = false;
if (oldState == GPS_IDLE) // If hardware already awake, no changes needed
break;
if (oldState != GPS_ACTIVE && oldState != GPS_IDLE) // If hardware just waking now, clear buffer
clearBuffer();
@@ -1142,8 +1145,7 @@ int32_t GPS::runOnce()
// if gps_update_interval is <=10s, GPS never goes off, so we treat that differently
uint32_t updateInterval = Default::getConfiguredOrDefaultMs(config.position.gps_update_interval);
// 1. Got a time for the first time
bool gotTime = (getRTCQuality() >= RTCQualityGPS);
// 1. Got a time for the first time this cycle
if (!gotTime && lookForTime()) { // Note: we count on this && short-circuiting and not resetting the RTC time
gotTime = true;
}
+1
View File
@@ -163,6 +163,7 @@ class GPS : private concurrency::OSThread
uint32_t lastChecksumFailCount = 0;
uint8_t currentStep = 0;
int32_t currentDelay = 2000;
bool gotTime = false;
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
+2 -2
View File
@@ -262,8 +262,8 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
} else if (q == RTCQualityGPS) {
shouldSet = true;
LOG_DEBUG("Reapply GPS time: %ld secs", printableEpoch);
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (12 * 60 * 60 * 1000UL))) {
// Every 12 hrs we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (30 * 60 * 1000UL))) {
// Every 30 minutes we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
shouldSet = true;
LOG_DEBUG("Reapply external time to correct clock drift %ld secs", printableEpoch);
} else {
+4
View File
@@ -9,6 +9,7 @@
#include "FSCommon.h"
#include "MeshRadio.h"
#include "MeshService.h"
#include "MessageStore.h"
#include "NodeDB.h"
#include "PacketHistory.h"
#include "PowerFSM.h"
@@ -524,6 +525,9 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
if (transmitHistory) {
transmitHistory->clear();
}
#if HAS_SCREEN
messageStore.clearAllMessages();
#endif
// second, install default state (this will deal with the duplicate mac address issue)
installDefaultNodeDatabase();
installDefaultDeviceState();
+30 -7
View File
@@ -36,6 +36,17 @@
// Flag to indicate a heartbeat was received and we should send queue status
bool heartbeatReceived = false;
namespace
{
constexpr uint8_t FILES_MANIFEST_LEVELS = 3;
constexpr size_t FILES_MANIFEST_MAX_COUNT = 64;
void releaseFilesManifest(std::vector<meshtastic_FileInfo> &filesManifest)
{
std::vector<meshtastic_FileInfo>().swap(filesManifest);
}
} // namespace
PhoneAPI::PhoneAPI()
{
lastContactMsec = millis();
@@ -70,10 +81,23 @@ void PhoneAPI::handleStartConfig()
state = STATE_SEND_MY_INFO;
}
pauseBluetoothLogging = true;
spiLock->lock();
filesManifest = getFiles("/", 10);
spiLock->unlock();
LOG_DEBUG("Got %d files in manifest", filesManifest.size());
// Manifest is never read on the node-info-only path (STATE_SEND_FILEMANIFEST
// short-circuits to sendConfigComplete), so skip the SPI lock + FS walk.
if (config_nonce != SPECIAL_NONCE_ONLY_NODES) {
bool filesManifestLimited = false;
{
concurrency::LockGuard guard(spiLock);
filesManifest = getFiles("/", FILES_MANIFEST_LEVELS, FILES_MANIFEST_MAX_COUNT, &filesManifestLimited);
}
if (filesManifestLimited) {
LOG_WARN("Got %zu files in manifest (limited to %zu entries/depth %u)", filesManifest.size(),
FILES_MANIFEST_MAX_COUNT, static_cast<unsigned>(FILES_MANIFEST_LEVELS));
} else {
LOG_DEBUG("Got %zu files in manifest", filesManifest.size());
}
} else {
releaseFilesManifest(filesManifest);
}
LOG_INFO("Start API client config millis=%u", millis());
// Protect against concurrent BLE callbacks: they run in NimBLE's FreeRTOS task and also touch nodeInfoQueue.
@@ -122,8 +146,7 @@ void PhoneAPI::close()
nodeInfoQueue.clear();
}
packetForPhone = NULL;
filesManifest.clear();
filesManifest.shrink_to_fit();
releaseFilesManifest(filesManifest);
lastPortNumToRadio.clear();
fromRadioNum = 0;
config_nonce = 0;
@@ -532,7 +555,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
if (config_state == filesManifest.size() ||
config_nonce == SPECIAL_NONCE_ONLY_NODES) { // also handles an empty filesManifest
config_state = 0;
filesManifest.clear();
releaseFilesManifest(filesManifest);
// Skip to complete packet
sendConfigComplete();
} else {
+2
View File
@@ -32,6 +32,8 @@
#include "STM32WLE5JCInterface.h"
#endif
Observable<uint32_t> RadioInterface::loraRxPacketObservable;
#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora) \
{ \
meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \
+3
View File
@@ -123,6 +123,9 @@ class RadioInterface
virtual ~RadioInterface() {}
/// Fires once per valid received LoRa packet (arg = sender NodeNum). Used e.g. to flash LED_LORA.
static Observable<uint32_t> loraRxPacketObservable;
/**
* Coerce LoRa config fields (bandwidth/spread_factor) derived from presets.
* This is used during early bootstrapping so UIs that display these fields directly remain consistent.
+10
View File
@@ -509,6 +509,9 @@ void RadioLibInterface::completeSending()
// that can take a long time
auto p = sendingPacket;
sendingPacket = NULL;
#ifdef LED_LORA
digitalWrite(LED_LORA, LED_STATE_OFF);
#endif
if (p) {
// Packet has been sent, count it toward our TX airtime utilization.
@@ -611,6 +614,10 @@ void RadioLibInterface::handleReceiveInterrupt()
printPacket("Lora RX", mp);
#ifdef LED_LORA
loraRxPacketObservable.notifyObservers(mp->from);
#endif
airTime->logAirtime(RX_LOG, rxMsec);
deliverToReceiver(mp);
@@ -686,6 +693,9 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
enableInterrupt(isrTxLevel0);
lastTxStart = millis();
printPacket("Started Tx", txp);
#ifdef LED_LORA
digitalWrite(LED_LORA, LED_STATE_ON);
#endif
}
return res == RADIOLIB_ERR_NONE;
+10 -2
View File
@@ -83,7 +83,11 @@ void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChan
// Do NOT override explicit broadcast replies
// Only reuse lastDest in LaunchRepeatDestination()
dest = newDest;
if (newDest == 0) {
dest = NODENUM_BROADCAST;
} else {
dest = newDest;
}
channel = newChannel;
lastDest = dest;
@@ -123,7 +127,11 @@ void CannedMessageModule::LaunchFreetextWithDestination(NodeNum newDest, uint8_t
// Do NOT override explicit broadcast replies
// Only reuse lastDest in LaunchRepeatDestination()
dest = newDest;
if (newDest == 0) {
dest = NODENUM_BROADCAST;
} else {
dest = newDest;
}
channel = newChannel;
lastDest = dest;
+38
View File
@@ -1,6 +1,7 @@
#include "StatusLEDModule.h"
#include "MeshService.h"
#include "configuration.h"
#include "mesh/RadioInterface.h"
#include <Arduino.h>
/*
@@ -17,6 +18,9 @@ StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
if (inputBroker)
inputObserver.observe(inputBroker);
#endif
#ifdef LED_LORA
loraRxObserver.observe(&RadioInterface::loraRxPacketObservable);
#endif
#ifdef NEOPIXEL_STATUS_POWER_PIN
powerPixel.begin();
powerPixel.clear();
@@ -90,6 +94,18 @@ int StatusLEDModule::handleInputEvent(const InputEvent *event)
return 0;
}
#endif
#ifdef LED_LORA
int StatusLEDModule::handleLoRaRx(uint32_t)
{
// Briefly flash LED_LORA on each received packet. Turn it on now (we share the main thread with
// the radio's receive handler, so this is safe) and wake runOnce() at flash end to turn it off.
digitalWrite(LED_LORA, LED_STATE_ON);
LORA_LED_state = LED_STATE_ON;
LORA_LED_starttime = millis();
setIntervalFromNow(LORA_RX_LED_FLASH_MS);
return 0;
}
#endif
int32_t StatusLEDModule::runOnce()
{
@@ -115,6 +131,12 @@ int32_t StatusLEDModule::runOnce()
CHARGE_LED_state = LED_STATE_OFF;
}
}
} else {
#if defined(LED_HEARTBEAT)
// If we are using the heartbeat, as in the Thinknode M4, we need to explicitly turn off the charge LED
// This probably implies that in the future we need to stop re-using this bool for multiple purposes.
CHARGE_LED_state = LED_STATE_OFF;
#endif
}
// If we want a LED to be dedicated to the simple hearbeat, we can use that instead of the charge LED
#if defined(LED_HEARTBEAT)
@@ -142,6 +164,7 @@ int32_t StatusLEDModule::runOnce()
}
}
#endif
#ifdef LED_PAIRING
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis() || doing_fast_blink) {
PAIRING_LED_state = LED_STATE_OFF;
} else if (ble_state == unpaired) {
@@ -156,6 +179,7 @@ int32_t StatusLEDModule::runOnce()
} else {
PAIRING_LED_state = LED_STATE_ON;
}
#endif
// Override if disabled in config
if (config.device.led_heartbeat_disabled) {
@@ -227,6 +251,20 @@ int32_t StatusLEDModule::runOnce()
digitalWrite(Battery_LED_4, chargeIndicatorLED4);
#endif
#ifdef LED_LORA
// End the LoRa-RX flash once its duration has elapsed; otherwise make sure we come back
// exactly at flash end (only ever clamp my_interval down, so other LED timing is preserved).
if (LORA_LED_state == LED_STATE_ON) {
uint32_t elapsed = millis() - LORA_LED_starttime;
if (elapsed >= LORA_RX_LED_FLASH_MS) {
digitalWrite(LED_LORA, LED_STATE_OFF);
LORA_LED_state = LED_STATE_OFF;
} else if ((uint32_t)my_interval > LORA_RX_LED_FLASH_MS - elapsed) {
my_interval = LORA_RX_LED_FLASH_MS - elapsed;
}
}
#endif
return (my_interval);
}
+12
View File
@@ -43,6 +43,9 @@ class StatusLEDModule : private concurrency::OSThread
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
int handleInputEvent(const InputEvent *arg);
#endif
#ifdef LED_LORA
int handleLoRaRx(uint32_t sender);
#endif
void setPowerLED(bool);
@@ -65,6 +68,10 @@ class StatusLEDModule : private concurrency::OSThread
CallbackObserver<StatusLEDModule, const InputEvent *> inputObserver =
CallbackObserver<StatusLEDModule, const InputEvent *>(this, &StatusLEDModule::handleInputEvent);
#endif
#ifdef LED_LORA
CallbackObserver<StatusLEDModule, uint32_t> loraRxObserver =
CallbackObserver<StatusLEDModule, uint32_t>(this, &StatusLEDModule::handleLoRaRx);
#endif
private:
bool CHARGE_LED_state = LED_STATE_OFF;
@@ -77,6 +84,11 @@ class StatusLEDModule : private concurrency::OSThread
uint32_t lastUserbuttonTime = 0;
uint32_t POWER_LED_starttime = 0;
bool doing_fast_blink = false;
#ifdef LED_LORA
static constexpr uint32_t LORA_RX_LED_FLASH_MS = 100;
bool LORA_LED_state = LED_STATE_OFF;
uint32_t LORA_LED_starttime = 0;
#endif
enum PowerState { discharging, charging, charged, critical };
+5 -2
View File
@@ -15,6 +15,7 @@
#endif
#include "esp_mac.h"
#include "freertosinc.h"
#include "meshUtils.h"
#include "sleep.h"
#include "soc/rtc.h"
@@ -261,6 +262,8 @@ void cpuDeepSleep(uint32_t msecToWake)
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
esp_deep_sleep_start(); // TBD mA sleep current (battery)
// User shutdown (DELAY_FOREVER / portMAX_DELAY): no RTC timer — align with nRF52 system_off semantics.
if (msecToWake != portMAX_DELAY)
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
esp_deep_sleep_start();
}
@@ -18,7 +18,9 @@
#define BATTERY_PIN 8
#define ADC_CHANNEL ADC1_GPIO8_CHANNEL
#define ADC_MULTIPLIER 2.0 // 2.0 + 10% for correction of display undervoltage.
#define ADC_MULTIPLIER 2.0
#define OCV_ARRAY 4100, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100
#define PIN_BUZZER 9
@@ -9,4 +9,6 @@ void initVariant()
{
pinMode(LED_PAIRING, OUTPUT);
digitalWrite(LED_PAIRING, !LED_STATE_ON); // Turn off the LED to start
pinMode(LED_LORA, OUTPUT);
digitalWrite(LED_LORA, !LED_STATE_ON); // Turn off the LED to start
}
@@ -37,6 +37,9 @@ extends = env:picomputer-s3
build_flags =
${env:picomputer-s3.build_flags}
-D MESHTASTIC_EXCLUDE_WEBSERVER=1
; device-ui's I2CKeyboardScanner unconditionally calls Wire.begin(I2C_SDA, I2C_SCL);
-D I2C_SDA=8
-D I2C_SCL=9
-D INPUTDRIVER_MATRIX_TYPE=1
-D USE_PIN_BUZZER=PIN_BUZZER
-D USE_SX127x
@@ -19,14 +19,14 @@ custom_meshtastic_support_level = 1
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_partition_scheme = 16MB
custom_meshtastic_has_mui = true
extends = esp32s3_base
board = wiscore_rak3312
board_check = true
upload_protocol = esptool
board_build.partitions = default_8MB.csv
board_build.partitions = default_16MB.csv
build_flags =
${esp32s3_base.build_flags}
@@ -53,6 +53,7 @@
#define BATTERY_PIN 1
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_MULTIPLIER 1.667
#define OCV_ARRAY 4160, 4020, 3940, 3870, 3810, 3760, 3740, 3720, 3680, 3620, 2990
#define PIN_BUZZER 38
+6 -7
View File
@@ -55,9 +55,9 @@ build_flags =
-D HAS_TFT=1
-D USE_I2S_BUZZER
-D RAM_SIZE=5120
-D LV_LVGL_H_INCLUDE_SIMPLE
-D LV_CONF_INCLUDE_SIMPLE
-D LV_COMP_CONF_INCLUDE_SIMPLE
-D LV_LVGL_H_INCLUDE_SIMPLE
-D LV_CONF_INCLUDE_SIMPLE
-D LV_COMP_CONF_INCLUDE_SIMPLE
-D LV_USE_SYSMON=0
-D LV_USE_PROFILER=0
-D LV_USE_PERF_MONITOR=0
@@ -72,6 +72,7 @@ build_flags =
; -D CALIBRATE_TOUCH=0
-D LGFX_SCREEN_WIDTH=240
-D LGFX_SCREEN_HEIGHT=320
-D LGFX_BUFSIZE=153600
-D DISPLAY_SIZE=320x240 ; landscape mode
-D LGFX_DRIVER=LGFX_TDECK
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_T_DECK.h\"
@@ -79,13 +80,11 @@ build_flags =
; -D GFX_DRIVER_INC=\"graphics/LVGL/LVGL_T_DECK.h\"
; -D LV_USE_ST7789=1
-D VIEW_320x240
; -D USE_DOUBLE_BUFFER
-D USE_PACKET_API
-D MAP_FULL_REDRAW
-D CUSTOM_TOUCH_DRIVER
; -D CUSTOM_TOUCH_DRIVER
lib_deps =
${env:t-deck.lib_deps}
${device-ui_base.lib_deps}
# renovate: datasource=github-tags depName=bb_captouch packageName=bitbank2/bb_captouch
https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip
;https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip
+1 -1
View File
@@ -2,7 +2,7 @@
[portduino_base]
platform =
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
https://github.com/meshtastic/platform-native/archive/cab4b21d902973e43c938dab3cf4844ba02547ec.zip
https://github.com/meshtastic/platform-native/archive/61067ac3774e4fe27aa9762c72cebea507f116c8.zip
framework = arduino
build_src_filter =
+1 -1
View File
@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 7
build = 26
build = 27