mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-31 06:02:02 +00:00
Compare commits
111 Commits
v2.6.5.fc3
...
event/dayt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a39d72e91 | ||
|
|
c2a38357f1 | ||
|
|
3aee4bfc6b | ||
|
|
981ecfdb61 | ||
|
|
ca9bf6b31a | ||
|
|
ff2a12d579 | ||
|
|
3a6fc668d8 | ||
|
|
b657ba1abb | ||
|
|
6f256c06f6 | ||
|
|
86217111b2 | ||
|
|
57d6c1fa85 | ||
|
|
62421a83fd | ||
|
|
867f50ab11 | ||
|
|
1e81ebed06 | ||
|
|
dd2cf633b0 | ||
|
|
fdbe16f650 | ||
|
|
a2903921cd | ||
|
|
2d6181fca0 | ||
|
|
a32e45f8f2 | ||
|
|
055fdcb7f6 | ||
|
|
8bb1f3e869 | ||
|
|
d75c91a760 | ||
|
|
9d31d9f43b | ||
|
|
152b8b1b02 | ||
|
|
10693c4569 | ||
|
|
7da8aea1df | ||
|
|
baae2503d5 | ||
|
|
947191a797 | ||
|
|
987623567a | ||
|
|
a8ab6e82e6 | ||
|
|
5c005aaed5 | ||
|
|
f9fbc3ff86 | ||
|
|
124f4daa71 | ||
|
|
00e2ac33ad | ||
|
|
845088e45b | ||
|
|
e0b1fdb5e8 | ||
|
|
a7ef9e9c08 | ||
|
|
216fbf2343 | ||
|
|
635de2d229 | ||
|
|
72eae42b81 | ||
|
|
b4e8f7dbb6 | ||
|
|
473ef1bc03 | ||
|
|
ca8c177363 | ||
|
|
77e6868d5d | ||
|
|
54c1423039 | ||
|
|
03f19bca0e | ||
|
|
89df9d7686 | ||
|
|
45fcd479f6 | ||
|
|
b1e35cd8b3 | ||
|
|
70ced735d9 | ||
|
|
24e9539d40 | ||
|
|
72dd5bd88d | ||
|
|
8812eadd44 | ||
|
|
48dc0e014c | ||
|
|
e03f3de185 | ||
|
|
5d48d2c0a7 | ||
|
|
2b57ffafd7 | ||
|
|
a30f431b6a | ||
|
|
916afb5098 | ||
|
|
d26b50b78c | ||
|
|
c6e5ec055f | ||
|
|
5ab1db0142 | ||
|
|
64a1cd3f99 | ||
|
|
9da141aa8c | ||
|
|
74b3dc34e4 | ||
|
|
e2f6600cb9 | ||
|
|
ef14967fbf | ||
|
|
c177c6d655 | ||
|
|
a36f21b29a | ||
|
|
d74359abf0 | ||
|
|
5fd64d4114 | ||
|
|
816d948ee5 | ||
|
|
e0dafc3618 | ||
|
|
4a9a59342a | ||
|
|
5699d8632e | ||
|
|
e5cd0d613c | ||
|
|
64c8bde04a | ||
|
|
4477031971 | ||
|
|
1138f74e2c | ||
|
|
cf5c8de92e | ||
|
|
7e8294dfad | ||
|
|
98411d408a | ||
|
|
040a34fca8 | ||
|
|
ecd9f015d8 | ||
|
|
4e30023a4b | ||
|
|
b46aad85cc | ||
|
|
c4dc3472ac | ||
|
|
28e62e53e5 | ||
|
|
3eb845eaae | ||
|
|
e4c2730f71 | ||
|
|
e7d0837d01 | ||
|
|
e7ce910c3b | ||
|
|
e957009019 | ||
|
|
7079f538ed | ||
|
|
baa05aacf5 | ||
|
|
4ef9eae695 | ||
|
|
854d74f8db | ||
|
|
91f38797a8 | ||
|
|
06ce6f3e8a | ||
|
|
3694805938 | ||
|
|
5c13f3451c | ||
|
|
1008a08c99 | ||
|
|
e98da27446 | ||
|
|
daa03aba30 | ||
|
|
456f94511f | ||
|
|
1888342a57 | ||
|
|
8e40d88e24 | ||
|
|
0d8e39cc2a | ||
|
|
78fa4c5c70 | ||
|
|
536b6d87c6 | ||
|
|
5256ae90dc |
29
.github/dependabot.yml
vendored
29
.github/dependabot.yml
vendored
@@ -1,29 +0,0 @@
|
||||
#trunk-ignore-all(yamllint/quoted-strings): required by dependabot syntax check
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: docker
|
||||
directory: /.devcontainer
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: gitsubmodule
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
ignore:
|
||||
- dependency-name: protobufs
|
||||
- package-ecosystem: github-actions
|
||||
directory: /.github/workflows
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00"
|
||||
timezone: US/Pacific
|
||||
7
.github/workflows/docker_build.yml
vendored
7
.github/workflows/docker_build.yml
vendored
@@ -26,6 +26,11 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
pio_env:
|
||||
description: PlatformIO environment to build
|
||||
required: false
|
||||
type: string
|
||||
default: native
|
||||
outputs:
|
||||
digest:
|
||||
description: Digest of built image
|
||||
@@ -90,3 +95,5 @@ jobs:
|
||||
push: ${{ inputs.push }}
|
||||
tags: ${{ steps.meta.outputs.tags }} # Tag is only meant to be consumed by the "manifest" job
|
||||
platforms: ${{ inputs.platform }}
|
||||
build-args: |
|
||||
PIO_ENV=${{ inputs.pio_env }}
|
||||
|
||||
104
.github/workflows/main_matrix.yml
vendored
104
.github/workflows/main_matrix.yml
vendored
@@ -5,14 +5,20 @@ concurrency:
|
||||
on:
|
||||
# # Triggers the workflow on push but only for the master branch
|
||||
push:
|
||||
branches: [master, develop]
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- event/*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- version.properties
|
||||
|
||||
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
||||
pull_request_target:
|
||||
branches: [master, develop]
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- event/*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
#- "**.yml"
|
||||
@@ -32,12 +38,12 @@ jobs:
|
||||
name: Checkout base
|
||||
- id: jsonStep
|
||||
run: |
|
||||
if [[ "${{ github.head_ref }}" == "" ]]; then
|
||||
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
||||
else
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
|
||||
fi
|
||||
echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} } Ref: ${{ github.ref }} Targets: $TARGETS"
|
||||
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
|
||||
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||
outputs:
|
||||
esp32: ${{ steps.jsonStep.outputs.esp32 }}
|
||||
@@ -143,9 +149,10 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
test-native:
|
||||
if: ${{ !contains(github.ref_name, 'event/') }}
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
docker-debian-amd64:
|
||||
docker-deb-amd64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
@@ -153,7 +160,16 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-alpine-amd64:
|
||||
docker-deb-amd64-tft:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-alp-amd64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
@@ -161,7 +177,16 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
|
||||
docker-debian-arm64:
|
||||
docker-alp-amd64-tft:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: alpine
|
||||
platform: linux/amd64
|
||||
runs-on: ubuntu-24.04
|
||||
push: false
|
||||
pio_env: native-tft
|
||||
|
||||
docker-deb-arm64:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
@@ -169,7 +194,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
docker-debian-armv7:
|
||||
docker-deb-armv7:
|
||||
uses: ./.github/workflows/docker_build.yml
|
||||
with:
|
||||
distro: debian
|
||||
@@ -177,17 +202,6 @@ jobs:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
push: false
|
||||
|
||||
after-checks:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
needs: [check]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
gather-artifacts:
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -332,7 +346,7 @@ jobs:
|
||||
merge-multiple: true
|
||||
path: ./output/pio-deps-native-tft
|
||||
|
||||
- name: Zip linux sources
|
||||
- name: Zip Linux sources
|
||||
working-directory: output
|
||||
run: |
|
||||
zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
|
||||
@@ -342,7 +356,9 @@ jobs:
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Add linux sources to release
|
||||
- name: Add Linux sources to GtiHub Release
|
||||
# Only run when targeting master branch with workflow_dispatch
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
run: |
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip
|
||||
@@ -400,9 +416,53 @@ jobs:
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Add bins and debug elfs to release
|
||||
- name: Add bins and debug elfs to GitHub Release
|
||||
# Only run when targeting master branch with workflow_dispatch
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
run: |
|
||||
gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
publish-firmware:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
needs: [release-firmware]
|
||||
env:
|
||||
targets: esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,stm32
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: firmware-{${{ env.targets }}}-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./publish
|
||||
|
||||
- name: Publish firmware to meshtastic.github.io
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
env:
|
||||
# On event/* branches, use the event name as the destination prefix
|
||||
DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }}
|
||||
with:
|
||||
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
|
||||
external_repository: meshtastic/meshtastic.github.io
|
||||
publish_branch: master
|
||||
publish_dir: ./publish
|
||||
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ steps.version.outputs.long }}
|
||||
keep_files: true
|
||||
user_name: github-actions[bot]
|
||||
user_email: github-actions[bot]@users.noreply.github.com
|
||||
commit_message: ${{ steps.version.outputs.long }}
|
||||
enable_jekyll: true
|
||||
|
||||
47
.github/workflows/release_channels.yml
vendored
47
.github/workflows/release_channels.yml
vendored
@@ -46,11 +46,14 @@ jobs:
|
||||
|
||||
# Create a PR to bump version when a release is Published
|
||||
bump-version:
|
||||
if: ${{ github.event.release.published }}
|
||||
if: github.event.action == 'published'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -60,32 +63,44 @@ jobs:
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: |
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
env:
|
||||
BUILD_LOCATION: local
|
||||
|
||||
- name: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
run: |
|
||||
# Bump version.properties
|
||||
chmod +x ./bin/bump_version.py
|
||||
./bin/bump_version.py
|
||||
|
||||
- name: Get new release version string
|
||||
run: |
|
||||
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
|
||||
id: new_version
|
||||
|
||||
- name: Ensure debian deps are installed
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y devscripts
|
||||
|
||||
- name: Update debian changelog
|
||||
run: >-
|
||||
debian/ci_changelog.sh
|
||||
run: |
|
||||
# Update debian changelog
|
||||
chmod +x ./debian/ci_changelog.sh
|
||||
./debian/ci_changelog.sh
|
||||
|
||||
- name: Create version.properties pull request
|
||||
- name: Bump org.meshtastic.meshtasticd.metainfo.xml
|
||||
run: |
|
||||
# Bump org.meshtastic.meshtasticd.metainfo.xml
|
||||
pip install -r bin/bump_metainfo/requirements.txt -q
|
||||
chmod +x ./bin/bump_metainfo/bump_metainfo.py
|
||||
./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.new_version.outputs.short }}"
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: 1
|
||||
|
||||
- name: Create Bumps pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
title: Bump version.properties
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
title: Bump release version
|
||||
commit-message: automated bumps
|
||||
add-paths: |
|
||||
version.properties
|
||||
debian/changelog
|
||||
bin/org.meshtastic.meshtasticd.metainfo.xml
|
||||
|
||||
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -13,7 +13,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
semgrep-full:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: semgrep/semgrep
|
||||
|
||||
|
||||
2
.github/workflows/sec_sast_semgrep_pull.yml
vendored
2
.github/workflows/sec_sast_semgrep_pull.yml
vendored
@@ -6,7 +6,7 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
semgrep-diff:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: semgrep/semgrep
|
||||
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.22.12
|
||||
version: 1.22.15
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.6.7
|
||||
ref: v1.6.8
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- renovate@40.0.6
|
||||
- prettier@3.5.3
|
||||
- trufflehog@3.88.23
|
||||
- yamllint@1.37.0
|
||||
- trufflehog@3.88.28
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.8.3
|
||||
- terrascan@1.19.9
|
||||
- trivy@0.61.0
|
||||
- trivy@0.62.1
|
||||
- taplo@0.9.3
|
||||
- ruff@0.11.4
|
||||
- ruff@0.11.8
|
||||
- isort@6.0.1
|
||||
- markdownlint@0.44.0
|
||||
- oxipng@9.1.4
|
||||
- oxipng@9.1.5
|
||||
- svgo@3.3.2
|
||||
- actionlint@1.7.7
|
||||
- flake8@7.2.0
|
||||
@@ -27,7 +28,7 @@ lint:
|
||||
- shellcheck@0.10.0
|
||||
- black@25.1.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.24.2
|
||||
- gitleaks@8.25.1
|
||||
- clang-format@16.0.3
|
||||
ignore:
|
||||
- linters: [ALL]
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -1,20 +1,21 @@
|
||||
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore-all(trivy/DS002): We must run as root for this container
|
||||
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
FROM python:3.13-bookworm AS builder
|
||||
ARG PIO_ENV=native
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
# Install Dependencies
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
curl wget g++ zip git ca-certificates \
|
||||
curl wget g++ zip git ca-certificates pkg-config \
|
||||
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
|
||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config \
|
||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
|
||||
libx11-dev libinput-dev libxkbcommon-x11-dev \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --no-cache-dir -U platformio \
|
||||
&& mkdir /tmp/firmware
|
||||
@@ -24,7 +25,7 @@ WORKDIR /tmp/firmware
|
||||
COPY . /tmp/firmware
|
||||
|
||||
# Build
|
||||
RUN bash ./bin/build-native.sh && \
|
||||
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
|
||||
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
# Fetch web assets
|
||||
@@ -44,7 +45,9 @@ ENV TZ=Etc/UTC
|
||||
USER root
|
||||
|
||||
RUN apt-get update && apt-get --no-install-recommends -y install \
|
||||
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev liborcania2.3 libulfius2.7 libssl3 \
|
||||
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev \
|
||||
liborcania2.3 libulfius2.7 libssl3 \
|
||||
libx11-6 libinput10 libxkbcommon-x11-0 \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir -p /var/lib/meshtasticd \
|
||||
&& mkdir -p /etc/meshtasticd/config.d \
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
| Firmware Version | Supported |
|
||||
| ---------------- | ------------------ |
|
||||
| 2.5.x | :white_check_mark: |
|
||||
| <= 2.4.x | :x: |
|
||||
| 2.6.x | :white_check_mark: |
|
||||
| <= 2.5.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
# trunk-ignore-all(trivy/DS002): We must run as root for this container
|
||||
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
|
||||
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
|
||||
|
||||
FROM python:3.13-alpine3.21 AS builder
|
||||
|
||||
ARG PIO_ENV=native
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
|
||||
RUN apk --no-cache add \
|
||||
bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \
|
||||
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
|
||||
libx11-dev libinput-dev libxkbcommon-dev \
|
||||
&& rm -rf /var/cache/apk/* \
|
||||
&& pip install --no-cache-dir -U platformio \
|
||||
&& mkdir /tmp/firmware
|
||||
@@ -21,7 +22,7 @@ COPY . /tmp/firmware
|
||||
# Add `argp` for musl
|
||||
ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp"
|
||||
|
||||
RUN bash ./bin/build-native.sh && \
|
||||
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
|
||||
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
# ##### PRODUCTION BUILD #############
|
||||
@@ -33,11 +34,16 @@ USER root
|
||||
|
||||
RUN apk --no-cache add \
|
||||
libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
|
||||
libx11 libinput libxkbcommon \
|
||||
&& rm -rf /var/cache/apk/* \
|
||||
&& mkdir -p /var/lib/meshtasticd \
|
||||
&& mkdir -p /etc/meshtasticd/config.d \
|
||||
&& mkdir -p /etc/meshtasticd/ssl
|
||||
|
||||
# Fetch compiled binary from the builder
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
|
||||
# Copy config templates
|
||||
COPY ./bin/config.d /etc/meshtasticd/available.d
|
||||
|
||||
WORKDIR /var/lib/meshtasticd
|
||||
VOLUME /var/lib/meshtasticd
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
custom_esp32_kind = esp32
|
||||
platform = platformio/espressif32@6.10.0
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
|
||||
platformio/espressif32@6.10.0
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
@@ -44,13 +46,20 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server/archive/23665b3adc080a311dcbb586ed5941b5f94d6ea2.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/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip
|
||||
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
|
||||
h2zero/NimBLE-Arduino@^1.4.3
|
||||
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
||||
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
||||
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
|
||||
lewisxhe/XPowersLib@^0.2.7
|
||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||
rweather/Crypto@^0.4.0
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
[esp32c6_base]
|
||||
extends = esp32_base
|
||||
platform = https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
|
||||
platform =
|
||||
# Do not renovate until we have switched to pioarduino tagged builds
|
||||
https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
@@ -23,10 +25,14 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
|
||||
lewisxhe/XPowersLib@^0.2.7
|
||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||
rweather/Crypto@^0.4.0
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter} -<mesh/http>
|
||||
|
||||
@@ -16,4 +16,4 @@ build_flags =
|
||||
lib_ignore =
|
||||
${esp32_base.lib_ignore}
|
||||
NimBLE-Arduino
|
||||
libpax
|
||||
libpax
|
||||
|
||||
@@ -3,4 +3,3 @@ extends = esp32_base
|
||||
custom_esp32_kind = esp32s3
|
||||
|
||||
monitor_speed = 115200
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
[nrf52_base]
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
platform = platformio/nordicnrf52@^10.8.0
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/nordicnrf52 packageName=platformio/platform/nordicnrf52
|
||||
platformio/nordicnrf52@^10.8.0
|
||||
extends = arduino_base
|
||||
platform_packages =
|
||||
; our custom Git version until they merge our PR
|
||||
# TODO renovate
|
||||
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf
|
||||
; Don't renovate toolchain-gccarmnoneeabi
|
||||
platformio/toolchain-gccarmnoneeabi@~1.90301.0
|
||||
|
||||
build_type = debug
|
||||
@@ -24,8 +28,9 @@ build_src_filter =
|
||||
lib_deps=
|
||||
${arduino_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
lvgl
|
||||
lvgl
|
||||
|
||||
@@ -6,7 +6,9 @@ build_flags = ${nrf52_base.build_flags}
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/e31a8825ea3300b163a0a3c1ddd5de34e10e1371.zip
|
||||
${environmental_extra.lib_deps}
|
||||
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
|
||||
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip
|
||||
|
||||
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native/archive/c5bd469ab9b5a6966321e09557b27d906961da63.zip
|
||||
platform =
|
||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||
https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
@@ -15,18 +17,19 @@ build_src_filter =
|
||||
+<mesh/raspihttp/>
|
||||
-<mesh/eth/>
|
||||
-<modules/esp32>
|
||||
-<modules/Telemetry/EnvironmentTelemetry.cpp>
|
||||
-<modules/Telemetry/AirQualityTelemetry.cpp>
|
||||
-<modules/Telemetry/Sensor>
|
||||
+<../variants/portduino>
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
${environmental_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
|
||||
lovyan03/LovyanGFX@^1.2.0
|
||||
https://github.com/pine64/libch341-spi-userspace/archive/a9b17e3452f7fb747000d9b4ad4409155b39f6ef.zip
|
||||
# renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main
|
||||
https://github.com/pine64/libch341-spi-userspace/archive/af9bc27c9c30fa90772279925b7c5913dff789b4.zip
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
@@ -42,4 +45,7 @@ build_flags =
|
||||
-lyaml-cpp
|
||||
-li2c
|
||||
-luv
|
||||
-std=gnu17
|
||||
-std=c++17
|
||||
|
||||
lib_ignore = Adafruit NeoPixel
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
|
||||
platform =
|
||||
# TODO renovate
|
||||
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
|
||||
; For arduino-pico >= 4.4.3
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
||||
platform_packages =
|
||||
# TODO renovate
|
||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -23,5 +28,7 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
; Common settings for rp2350 Processor based targets
|
||||
[rp2350_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
|
||||
platform =
|
||||
# TODO renovate
|
||||
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
|
||||
; For arduino-pico >= 4.4.3
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
||||
platform_packages =
|
||||
# TODO renovate
|
||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -20,5 +25,7 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${environmental_extra.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto
|
||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||
rweather/Crypto@0.4.0
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
[stm32_base]
|
||||
extends = arduino_base
|
||||
platform = ststm32
|
||||
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
|
||||
platform =
|
||||
# renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32
|
||||
platformio/ststm32@19.1.0
|
||||
platform_packages =
|
||||
# TODO renovate
|
||||
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
|
||||
extra_scripts =
|
||||
${env.extra_scripts}
|
||||
post:extra_scripts/extra_stm32.py
|
||||
@@ -35,6 +39,7 @@ debug_tool = stlink
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=caveman99-stm32-Crypto packageName=https://github.com/caveman99/Crypto gitBranch=main
|
||||
https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip
|
||||
|
||||
lib_ignore =
|
||||
|
||||
@@ -15,6 +15,7 @@ platformioFailed() {
|
||||
|
||||
VERSION=$(bin/buildinfo.py long)
|
||||
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||
PIO_ENV=${1:-native}
|
||||
|
||||
OUTDIR=release/
|
||||
|
||||
@@ -24,7 +25,7 @@ mkdir -p $OUTDIR/
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
pio pkg update --environment native || platformioFailed
|
||||
pio run --environment native || platformioFailed
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
pio pkg update --environment "$PIO_ENV" || platformioFailed
|
||||
pio run --environment "$PIO_ENV" || platformioFailed
|
||||
cp ".pio/build/$PIO_ENV/program" "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
cp bin/native-install.* $OUTDIR
|
||||
|
||||
72
bin/bump_metainfo/bump_metainfo.py
Executable file
72
bin/bump_metainfo/bump_metainfo.py
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import xml.etree.ElementTree as ET
|
||||
from defusedxml.ElementTree import parse
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
# Indent by 2 spaces to align with xml formatting.
|
||||
def indent(elem, level=0):
|
||||
i = "\n" + level * " "
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = i + " "
|
||||
for child in elem:
|
||||
indent(child, level + 1)
|
||||
if not child.tail or not child.tail.strip():
|
||||
child.tail = i
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = i
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Prepend new release entry to metainfo.xml file.")
|
||||
parser.add_argument("--file", help="Path to the metainfo.xml file",
|
||||
default="org.meshtastic.meshtasticd.metainfo.xml")
|
||||
parser.add_argument("version", help="Version string (e.g. 2.6.4)")
|
||||
parser.add_argument("--date", help="Release date (YYYY-MM-DD), defaults to today",
|
||||
default=datetime.now(timezone.utc).date().isoformat())
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
tree = parse(args.file)
|
||||
root = tree.getroot()
|
||||
|
||||
releases = root.find('releases')
|
||||
if releases is None:
|
||||
raise RuntimeError("<releases> element not found in XML.")
|
||||
|
||||
existing_versions = {
|
||||
release.get('version'): release
|
||||
for release in releases.findall('release')
|
||||
}
|
||||
existing_release = existing_versions.get(args.version)
|
||||
|
||||
if existing_release is not None:
|
||||
if not existing_release.get('date'):
|
||||
print(f"Version {args.version} found without date. Adding date...")
|
||||
existing_release.set('date', args.date)
|
||||
else:
|
||||
print(
|
||||
f"Version {args.version} is already present with date, skipping insertion.")
|
||||
else:
|
||||
new_release = ET.Element('release', {
|
||||
'version': args.version,
|
||||
'date': args.date
|
||||
})
|
||||
url = ET.SubElement(new_release, 'url', {'type': 'details'})
|
||||
url.text = f"https://github.com/meshtastic/firmware/releases?q=tag%3Av{args.version}"
|
||||
|
||||
releases.insert(0, new_release)
|
||||
|
||||
indent(releases, level=1)
|
||||
releases.tail = "\n"
|
||||
|
||||
print(f"Inserted new release: {args.version}")
|
||||
|
||||
tree.write(args.file, encoding='UTF-8', xml_declaration=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
bin/bump_metainfo/requirements.txt
Normal file
1
bin/bump_metainfo/requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
defusedxml==0.7.1
|
||||
11
bin/config.d/lora-piggystick-lr1121.yaml
Normal file
11
bin/config.d/lora-piggystick-lr1121.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
Lora:
|
||||
Module: lr1121
|
||||
CS: 0
|
||||
IRQ: 6
|
||||
Reset: 2
|
||||
Busy: 4
|
||||
spidev: ch341
|
||||
DIO3_TCXO_VOLTAGE: 1.8
|
||||
# USB_Serialnum: 12345678
|
||||
USB_PID: 0x5512
|
||||
USB_VID: 0x1A86
|
||||
@@ -17,8 +17,8 @@ SET "LOGCOUNTER=0"
|
||||
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
|
||||
SET "C3=esp32c3"
|
||||
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
|
||||
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core t-watch-s3 tracksenger"
|
||||
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite"
|
||||
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
|
||||
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3"
|
||||
|
||||
GOTO getopts
|
||||
:help
|
||||
|
||||
@@ -22,7 +22,6 @@ BIGDB_8MB=(
|
||||
"icarus"
|
||||
"seeed-xiao-s3"
|
||||
"tbeam-s3-core"
|
||||
"t-watch-s3"
|
||||
"tracksenger"
|
||||
)
|
||||
BIGDB_16MB=(
|
||||
@@ -34,6 +33,7 @@ BIGDB_16MB=(
|
||||
"m5stack-cores3"
|
||||
"station-g2"
|
||||
"t-eth-elite"
|
||||
"t-watch-s3"
|
||||
)
|
||||
S3_VARIANTS=(
|
||||
"s3"
|
||||
|
||||
8
bin/org.meshtastic.meshtasticd.desktop
Normal file
8
bin/org.meshtastic.meshtasticd.desktop
Normal file
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Name=Meshtastic
|
||||
Comment=Meshtastic App
|
||||
Exec=meshtasticd
|
||||
Icon=org.meshtastic.meshtasticd
|
||||
Terminal=true
|
||||
Type=Application
|
||||
Categories=Network;Chat;HamRadio;
|
||||
106
bin/org.meshtastic.meshtasticd.metainfo.xml
Normal file
106
bin/org.meshtastic.meshtasticd.metainfo.xml
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<component type="desktop-application">
|
||||
<id>org.meshtastic.meshtasticd</id>
|
||||
|
||||
<name>Meshtastic</name>
|
||||
<summary>Decentralized mesh communication</summary>
|
||||
|
||||
<metadata_license>CC-BY-4.0</metadata_license>
|
||||
<project_license>GPL-3.0-or-later</project_license>
|
||||
|
||||
<developer id="org.meshtastic">
|
||||
<name>Meshtastic</name>
|
||||
</developer>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
Meshtastic is an open source project for creating off-grid, affordable, and resilient communication with LoRa mesh networks.
|
||||
</p>
|
||||
</description>
|
||||
|
||||
<launchable type="desktop-id">org.meshtastic.meshtasticd.desktop</launchable>
|
||||
|
||||
<categories>
|
||||
<category>Network</category>
|
||||
<category>Chat</category>
|
||||
<category>HamRadio</category>
|
||||
</categories>
|
||||
<keywords>
|
||||
<keyword>mesh</keyword>
|
||||
<keyword>LoRa</keyword>
|
||||
</keywords>
|
||||
|
||||
<recommends>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
<control>touch</control>
|
||||
</recommends>
|
||||
<requires>
|
||||
<display_length compare="ge">360</display_length>
|
||||
</requires>
|
||||
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#97be89</color>
|
||||
<color type="primary" scheme_preference="dark">#206538</color>
|
||||
</branding>
|
||||
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
<content_attribute id="social-location">intense</content_attribute>
|
||||
</content_rating>
|
||||
|
||||
<url type="bugtracker">https://github.com/meshtastic/firmware/issues</url>
|
||||
<url type="homepage">https://meshtastic.org/</url>
|
||||
<url type="donation">https://opencollective.com/meshtastic</url>
|
||||
<url type="faq">https://meshtastic.org/docs/software/linux/usage/</url>
|
||||
<url type="vcs-browser">https://github.com/meshtastic/firmware/</url>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_home_dashboard_dark.webp</image>
|
||||
<caption>Home Dashboard</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_initial_boot.webp</image>
|
||||
<caption>Setup</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_node_list_dark.webp</image>
|
||||
<caption>Nodes List</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_list_dark.webp</image>
|
||||
<caption>Chats List</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_message_dark.webp</image>
|
||||
<caption>Messages</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_map_dark.webp</image>
|
||||
<caption>Map</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_settings_dark.webp</image>
|
||||
<caption>Settings</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.6.8" date="2025-05-05">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8</url>
|
||||
</release>
|
||||
<release version="2.6.7" date="2025-04-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7</url>
|
||||
</release>
|
||||
<release version="2.6.6" date="2025-04-15">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6</url>
|
||||
</release>
|
||||
<release version="2.6.5" date="2025-03-30">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.5</url>
|
||||
</release>
|
||||
<release version="2.6.4" date="2025-03-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.4</url>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
||||
16
bin/org.meshtastic.meshtasticd.svg
Normal file
16
bin/org.meshtastic.meshtasticd.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="512" height="512" viewBox="0 0 512 512" xml:space="preserve">
|
||||
<desc>Created with Fabric.js 4.6.0</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<g transform="matrix(1 0 0 1 256 256)" id="xYQ9Gk9Jwpgj_HMOXB3F_" >
|
||||
<path style="stroke: rgb(213,130,139); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(103,234,148); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-256, -256)" d="M 0 0 L 512 0 L 512 512 L 0 512 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(1.79 0 0 1.79 313.74 258.36)" id="1xBsk2n9FZp60Rz1O-ceJ" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-250.97, -362.41)" d="M 250.908 330.267 L 193.126 415.005 L 180.938 406.694 L 244.802 313.037 C 246.174 311.024 248.453 309.819 250.889 309.816 C 253.326 309.814 255.606 311.015 256.982 313.026 L 320.994 406.536 L 308.821 414.869 L 250.908 330.267 Z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(1.81 0 0 1.81 145 256.15)" id="KxN7E9YpbyPgz0S4z4Cl6" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-115.14, -528.06)" d="M 87.642 581.398 L 154.757 482.977 L 142.638 474.713 L 75.523 573.134 L 87.642 581.398 Z" stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1 +1 @@
|
||||
2.6.0
|
||||
2.5.3
|
||||
54
boards/Seeed_Solar_Node.json
Normal file
54
boards/Seeed_Solar_Node.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v7.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x2886", "0x0059"]],
|
||||
"usb_product": "XIAO-BOOT",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "Seeed_Solar_Node",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "7.3.0",
|
||||
"sd_fwid": "0x0123"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Seeed_Solar_Node",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"nrfutil",
|
||||
"stlink",
|
||||
"cmsis-dap",
|
||||
"blackmagic"
|
||||
],
|
||||
"use_1200bps_touch": true,
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html",
|
||||
"vendor": "Seeed Studio"
|
||||
}
|
||||
43
boards/crowpanel.json
Normal file
43
boards/crowpanel.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi",
|
||||
"partitions": "default_16MB.csv"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=0"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "ESP32-S3-WROOM-1-N16R8"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "ESP32-S3-WROOM-1-N16R8 (16 MB Flash, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 524288,
|
||||
"maximum_size": 16777216,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"monitor": {
|
||||
"speed": 115200
|
||||
},
|
||||
"url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
53
boards/heltec_mesh_pocket.json
Normal file
53
boards/heltec_mesh_pocket.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x4405"],
|
||||
["0x239A", "0x0029"],
|
||||
["0x239A", "0x002A"]
|
||||
],
|
||||
"usb_product": "HT-n5262",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "heltec_mesh_pocket",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Heltec nrf (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||
"use_1200bps_touch": true,
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "https://heltec.org/project/meshpocket/",
|
||||
"vendor": "Heltec"
|
||||
}
|
||||
@@ -24,16 +24,16 @@
|
||||
"mcu": "esp32s3",
|
||||
"variant": "t-watch-s3"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth"],
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "LilyGo T-Watch 2020 V3",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"maximum_size": 16777216,
|
||||
"require_upload_port": true,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
|
||||
BIN
data/boot/logo.png
Normal file
BIN
data/boot/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
8
debian/changelog
vendored
8
debian/changelog
vendored
@@ -1,9 +1,13 @@
|
||||
meshtasticd (2.5.22.0) UNRELEASED; urgency=medium
|
||||
meshtasticd (2.6.8.0) UNRELEASED; urgency=medium
|
||||
|
||||
[ Austin Lane ]
|
||||
* Initial packaging
|
||||
* GitHub Actions Automatic version bump
|
||||
* GitHub Actions Automatic version bump
|
||||
* GitHub Actions Automatic version bump
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- Austin Lane <github-actions[bot]@users.noreply.github.com> Wed, 05 Feb 2025 01:10:33 +0000
|
||||
[ ]
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- <github-actions[bot]@users.noreply.github.com> Tue, 06 May 2025 01:32:49 +0000
|
||||
|
||||
4
debian/ci_pack_sdeb.sh
vendored
4
debian/ci_pack_sdeb.sh
vendored
@@ -5,8 +5,8 @@ export PLATFORMIO_PACKAGES_DIR=pio/packages
|
||||
export PLATFORMIO_CORE_DIR=pio/core
|
||||
|
||||
# Download libraries to `pio`
|
||||
platformio pkg install -e native
|
||||
platformio pkg install -e native -t platformio/tool-scons@4.40502.0
|
||||
platformio pkg install -e native-tft
|
||||
platformio pkg install -e native-tft -t platformio/tool-scons@4.40502.0
|
||||
# Compress `pio` directory to prevent dh_clean from sanitizing it
|
||||
tar -cf pio.tar pio/
|
||||
rm -rf pio
|
||||
|
||||
5
debian/control
vendored
5
debian/control
vendored
@@ -21,7 +21,10 @@ Build-Depends: debhelper-compat (= 13),
|
||||
openssl,
|
||||
libssl-dev,
|
||||
libulfius-dev,
|
||||
liborcania-dev
|
||||
liborcania-dev,
|
||||
libx11-dev,
|
||||
libinput-dev,
|
||||
libxkbcommon-x11-dev
|
||||
Standards-Version: 4.6.2
|
||||
Homepage: https://github.com/meshtastic/firmware
|
||||
Rules-Requires-Root: no
|
||||
|
||||
10
debian/meshtasticd.install
vendored
10
debian/meshtasticd.install
vendored
@@ -1,8 +1,8 @@
|
||||
.pio/build/native/meshtasticd usr/sbin
|
||||
.pio/build/native-tft/meshtasticd usr/sbin
|
||||
|
||||
bin/config.yaml etc/meshtasticd
|
||||
bin/config.d/* etc/meshtasticd/available.d
|
||||
bin/config.yaml etc/meshtasticd
|
||||
bin/config.d/* etc/meshtasticd/available.d
|
||||
|
||||
bin/meshtasticd.service lib/systemd/system
|
||||
bin/meshtasticd.service lib/systemd/system
|
||||
|
||||
web/* usr/share/meshtasticd/web
|
||||
web/* usr/share/meshtasticd/web
|
||||
4
debian/rules
vendored
4
debian/rules
vendored
@@ -26,7 +26,7 @@ override_dh_auto_build:
|
||||
mkdir -p web && tar -xf web.tar -C web
|
||||
gunzip web/ -r
|
||||
# Build with platformio
|
||||
$(PIO_ENV) platformio run -e native
|
||||
$(PIO_ENV) platformio run -e native-tft
|
||||
# Move the binary and default config to the correct name
|
||||
mv .pio/build/native/program .pio/build/native/meshtasticd
|
||||
mv .pio/build/native-tft/program .pio/build/native-tft/meshtasticd
|
||||
cp bin/config-dist.yaml bin/config.yaml
|
||||
|
||||
@@ -42,6 +42,10 @@ BuildRequires: pkgconfig(openssl)
|
||||
BuildRequires: pkgconfig(liborcania)
|
||||
BuildRequires: pkgconfig(libyder)
|
||||
BuildRequires: pkgconfig(libulfius)
|
||||
# TFT components:
|
||||
BuildRequires: pkgconfig(x11)
|
||||
BuildRequires: pkgconfig(libinput)
|
||||
BuildRequires: pkgconfig(xkbcommon-x11)
|
||||
|
||||
%description
|
||||
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
|
||||
@@ -55,12 +59,12 @@ tar -xf %{SOURCE1} -C web
|
||||
gzip -dr web
|
||||
|
||||
%build
|
||||
# Use the “native” environment from platformio to build a Linux binary
|
||||
platformio run -e native
|
||||
# Use the “native-tft” environment from platformio to build a Linux binary
|
||||
platformio run -e native-tft
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}%{_sbindir}
|
||||
install -m 0755 .pio/build/native/program %{buildroot}%{_sbindir}/meshtasticd
|
||||
install -m 0755 .pio/build/native-tft/program %{buildroot}%{_sbindir}/meshtasticd
|
||||
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
|
||||
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml
|
||||
|
||||
@@ -50,18 +50,26 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
||||
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
|
||||
-DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1
|
||||
#-DBUILD_EPOCH=$UNIX_TIME
|
||||
#-D OLED_PL=1
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_filters = direct
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0119501e9983bd894830b02f545c377ee08d66fe.zip
|
||||
# renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton
|
||||
mathertel/OneButton@2.6.1
|
||||
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
|
||||
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master
|
||||
https://github.com/meshtastic/TinyGPSPlus/archive/71a82db35f3b973440044c476d4bcdc673b104f4.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-ArduinoThread packageName=https://github.com/meshtastic/ArduinoThread gitBranch=master
|
||||
https://github.com/meshtastic/ArduinoThread/archive/7c3ee9e1951551b949763b1f5280f8db1fa4068d.zip
|
||||
# renovate: datasource=custom.pio depName=Nanopb packageName=nanopb/library/Nanopb
|
||||
nanopb/Nanopb@0.4.91
|
||||
# renovate: datasource=custom.pio depName=ErriezCRC32 packageName=erriez/library/ErriezCRC32
|
||||
erriez/ErriezCRC32@1.0.1
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
@@ -77,6 +85,7 @@ check_flags =
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL
|
||||
end2endzone/NonBlockingRTTTL@1.3.0
|
||||
build_flags = ${env.build_flags} -Os
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/>
|
||||
@@ -84,57 +93,99 @@ build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/nic
|
||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||
[networking_base]
|
||||
lib_deps =
|
||||
knolleary/PubSubClient@2.8
|
||||
arduino-libraries/NTPClient@3.1.0
|
||||
# renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient
|
||||
thingsboard/TBPubSubClient@2.12.1
|
||||
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
|
||||
arduino-libraries/NTPClient@3.2.1
|
||||
# renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog
|
||||
arcao/Syslog@2.0.0
|
||||
|
||||
[radiolib_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
||||
jgromes/RadioLib@7.1.2
|
||||
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/device-ui/archive/56ef8db7eb4dda44dc0c1ec5828044debbbc6d33.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/09b1780c8f944cffbc18a8ec5713cdfe03278503.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
[environmental_base]
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@1.17.0
|
||||
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
|
||||
adafruit/Adafruit BusIO@1.17.1
|
||||
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
|
||||
adafruit/Adafruit Unified Sensor@1.1.15
|
||||
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
|
||||
adafruit/Adafruit BMP280 Library@2.6.8
|
||||
# renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library
|
||||
adafruit/Adafruit BMP085 Library@1.2.4
|
||||
adafruit/Adafruit BME280 Library@2.2.4
|
||||
adafruit/Adafruit BMP3XX Library@2.1.6
|
||||
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
|
||||
adafruit/Adafruit BME280 Library@2.3.0
|
||||
# renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310
|
||||
adafruit/Adafruit DPS310@1.1.5
|
||||
# renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library
|
||||
adafruit/Adafruit MCP9808 Library@2.0.2
|
||||
# renovate: datasource=custom.pio depName=Adafruit INA260 packageName=adafruit/library/Adafruit INA260 Library
|
||||
adafruit/Adafruit INA260 Library@1.5.2
|
||||
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
|
||||
adafruit/Adafruit INA219@1.2.3
|
||||
adafruit/Adafruit MAX1704X@1.0.3
|
||||
adafruit/Adafruit SHTC3 Library@1.0.1
|
||||
adafruit/Adafruit LPS2X@2.0.6
|
||||
adafruit/Adafruit SHT31 Library@2.2.2
|
||||
# renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor
|
||||
adafruit/Adafruit PM25 AQI Sensor@1.2.0
|
||||
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
|
||||
adafruit/Adafruit MPU6050@2.2.6
|
||||
# renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH
|
||||
adafruit/Adafruit LIS3DH@1.3.0
|
||||
# renovate: datasource=custom.pio depName=Adafruit AHTX0 packageName=adafruit/library/Adafruit AHTX0
|
||||
adafruit/Adafruit AHTX0@2.0.5
|
||||
# renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS
|
||||
adafruit/Adafruit LSM6DS@4.7.4
|
||||
adafruit/Adafruit VEML7700 Library@2.1.6
|
||||
adafruit/Adafruit SHT4x Library@1.0.5
|
||||
# renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library
|
||||
adafruit/Adafruit TSL2591 Library@1.4.5
|
||||
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
|
||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0
|
||||
ClosedCube OPT3001@1.1.2
|
||||
# renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632
|
||||
emotibit/EmotiBit MLX90632@1.0.8
|
||||
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
|
||||
adafruit/Adafruit MLX90614 Library@2.1.5
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip
|
||||
boschsensortec/BME68x Sensor Library@1.1.40407
|
||||
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
|
||||
boschsensortec/BME68x Sensor Library@1.2.40408
|
||||
# renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221
|
||||
https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip
|
||||
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
|
||||
mprograms/QMC5883LCompass@1.2.3
|
||||
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
|
||||
dfrobot/DFRobot_RTU@1.0.3
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
|
||||
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
|
||||
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
|
||||
# renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226
|
||||
robtillaart/INA226@0.6.4
|
||||
|
||||
; Health Sensor Libraries
|
||||
# renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
||||
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
|
||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2
|
||||
|
||||
; (not included in native / portduino)
|
||||
[environmental_extra]
|
||||
lib_deps =
|
||||
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
|
||||
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.1
|
||||
# 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
|
||||
ClosedCube OPT3001@1.1.2
|
||||
# renovate: datasource=git-refs depName=Bosch BSEC2 packageName=https://github.com/meshtastic/Bosch-BSEC2-Library gitBranch=extra_script
|
||||
https://github.com/meshtastic/Bosch-BSEC2-Library/archive/e16952dfe5addd4287e1eb8c4f6ecac0fa3dd3de.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
|
||||
|
||||
Submodule protobufs updated: 5a5ab103d2...078ac8dfbe
79
renovate.json
Normal file
79
renovate.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
":dependencyDashboard",
|
||||
":semanticCommitTypeAll(chore)",
|
||||
":ignoreModulesAndTests",
|
||||
"group:recommended",
|
||||
"replacements:all",
|
||||
"workarounds:all"
|
||||
],
|
||||
"forkProcessing": "enabled",
|
||||
"ignoreDeps": ["protobufs"],
|
||||
"git-submodules": {
|
||||
"enabled": true
|
||||
},
|
||||
"pip_requirements": {
|
||||
"fileMatch": ["bin/bump_metainfo/requirements.txt"]
|
||||
},
|
||||
"commitMessageTopic": "{{depName}}",
|
||||
"labels": ["dependencies"],
|
||||
"customDatasources": {
|
||||
"pio": {
|
||||
"description": "PlatformIO Registry",
|
||||
"defaultRegistryUrlTemplate": "https://api.registry.platformio.org/v3/packages/{{packageName}}",
|
||||
"format": "json",
|
||||
"transformTemplates": [
|
||||
"{\"releases\": [$map($.versions, function($v) { { \"version\": $v.name, \"releaseTimestamp\": $v.released_at } })], \"homepage\": $encodeUrl($join([\"https://registry.platformio.org/\",$.type,\"/\",$.owner.username,\"/\",$.name])) }"
|
||||
]
|
||||
}
|
||||
},
|
||||
"customManagers": [
|
||||
{
|
||||
"customType": "regex",
|
||||
"description": "Match meshtastic/web version",
|
||||
"fileMatch": ["bin/web.version"],
|
||||
"matchStrings": ["(?<currentValue>.+)$"],
|
||||
"datasourceTemplate": "github-releases",
|
||||
"depNameTemplate": "meshtastic/web",
|
||||
"versioningTemplate": "semver-coerced"
|
||||
},
|
||||
{
|
||||
"customType": "regex",
|
||||
"description": "Match normal PIO dependencies",
|
||||
"fileMatch": [".*\\.ini$"],
|
||||
"matchStrings": [
|
||||
"# renovate: datasource=(?<datasource>.*?)(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?.+?@(?<currentValue>.+?)\\s"
|
||||
],
|
||||
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
|
||||
},
|
||||
{
|
||||
"customType": "regex",
|
||||
"description": "Match PIO zipped dependencies with github tag ref",
|
||||
"fileMatch": [".*\\.ini$"],
|
||||
"matchStrings": [
|
||||
"# renovate: datasource=github-tags(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?https:\/\/.+?archive\/(?<currentValue>.+?).zip\\s"
|
||||
],
|
||||
"datasourceTemplate": "github-tags",
|
||||
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
|
||||
},
|
||||
{
|
||||
"customType": "regex",
|
||||
"description": "Match PIO zipped dependencies with git commit ref",
|
||||
"fileMatch": [".*\\.ini$"],
|
||||
"matchStrings": [
|
||||
"# renovate: datasource=git-refs(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\sgitBranch=(?<gitBranch>.+?)\\s+?https:\/\/.+?archive\/(?<currentDigest>.+?).zip\\s"
|
||||
],
|
||||
"datasourceTemplate": "git-refs",
|
||||
"currentValueTemplate": "{{{gitBranch}}}",
|
||||
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}git{{/if}}"
|
||||
}
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchDepNames": ["meshtastic/device-ui"],
|
||||
"reviewers": ["mverch67"],
|
||||
"changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -255,7 +255,7 @@ int32_t ButtonThread::runOnce()
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
break;
|
||||
#endif
|
||||
#if defined(RAK_4631)
|
||||
#if !MESHTASTIC_EXCLUDE_SCREEN && HAS_SCREEN
|
||||
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
|
||||
case 5:
|
||||
if (accelerometerThread) {
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
#include "SPILock.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
// Software SPI is used by MUI so disable SD card here until it's also implemented
|
||||
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#ifdef SDCARD_USE_SPI1
|
||||
SPIClass SPI1(HSPI);
|
||||
#define SDHandler SPI1
|
||||
SPIClass SPI_HSPI(HSPI);
|
||||
#define SDHandler SPI_HSPI
|
||||
#else
|
||||
#define SDHandler SPI
|
||||
#endif
|
||||
@@ -306,7 +307,7 @@ void fsInit()
|
||||
*/
|
||||
void setupSDCard()
|
||||
{
|
||||
#ifdef HAS_SDCARD
|
||||
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
|
||||
concurrency::LockGuard g(spiLock);
|
||||
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
|
||||
if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) {
|
||||
|
||||
@@ -76,23 +76,47 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#if __has_include(<Adafruit_INA219.h>)
|
||||
INA219Sensor ina219Sensor;
|
||||
INA226Sensor ina226Sensor;
|
||||
INA260Sensor ina260Sensor;
|
||||
INA3221Sensor ina3221Sensor;
|
||||
#else
|
||||
NullSensor ina219Sensor;
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#if __has_include(<INA226.h>)
|
||||
INA226Sensor ina226Sensor;
|
||||
#else
|
||||
NullSensor ina226Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<Adafruit_INA260.h>)
|
||||
INA260Sensor ina260Sensor;
|
||||
#else
|
||||
NullSensor ina260Sensor;
|
||||
#endif
|
||||
|
||||
#if __has_include(<INA3221.h>)
|
||||
INA3221Sensor ina3221Sensor;
|
||||
#else
|
||||
NullSensor ina3221Sensor;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL)
|
||||
#include "modules/Telemetry/Sensor/MAX17048Sensor.h"
|
||||
#include <utility>
|
||||
extern std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
|
||||
#if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY)
|
||||
#if __has_include(<Adafruit_MAX1704X.h>)
|
||||
MAX17048Sensor max17048Sensor;
|
||||
#else
|
||||
NullSensor max17048Sensor;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO)
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT
|
||||
RAK9154Sensor rak9154Sensor;
|
||||
#endif
|
||||
|
||||
@@ -203,7 +227,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
*/
|
||||
virtual int getBatteryPercent() override
|
||||
{
|
||||
#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
|
||||
#if defined(HAS_RAKPROT) && !defined(HAS_PMU)
|
||||
if (hasRAK()) {
|
||||
return rak9154Sensor.getBusBatteryPercent();
|
||||
}
|
||||
@@ -248,15 +272,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
virtual uint16_t getBattVoltage() override
|
||||
{
|
||||
|
||||
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && \
|
||||
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
if (hasRAK()) {
|
||||
return getRAKVoltage();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
|
||||
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#if HAS_TELEMETRY && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
if (hasINA()) {
|
||||
return getINAVoltage();
|
||||
}
|
||||
@@ -426,8 +448,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
/// we can't be smart enough to say 'full'?
|
||||
virtual bool isCharging() override
|
||||
{
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && \
|
||||
!defined(HAS_PMU)
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(HAS_PMU)
|
||||
if (hasRAK()) {
|
||||
return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse;
|
||||
}
|
||||
@@ -435,7 +456,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
|
||||
#else
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && \
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) && \
|
||||
!defined(DISABLE_INA_CHARGING_DETECTION)
|
||||
if (hasINA()) {
|
||||
// get current flow from INA sensor - negative value means power flowing into the battery
|
||||
@@ -450,6 +471,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
return isBatteryConnect() && isVbusIn();
|
||||
#endif
|
||||
#endif
|
||||
// by default, we check the battery voltage only
|
||||
return isVbusIn();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -480,7 +503,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL)
|
||||
uint16_t getINAVoltage()
|
||||
{
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO) || defined(MESHTASTIC_EXCLUDE_WIFI)
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
@@ -269,9 +269,6 @@ Fsm powerFSM(&stateBOOT);
|
||||
void PowerFSM_setup()
|
||||
{
|
||||
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
|
||||
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
|
||||
bool hasPower = isPowered();
|
||||
|
||||
LOG_INFO("PowerFSM init, USB power=%d", hasPower ? 1 : 0);
|
||||
@@ -383,6 +380,12 @@ void PowerFSM_setup()
|
||||
// See: https://github.com/meshtastic/firmware/issues/1071
|
||||
// Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated
|
||||
// through the modules
|
||||
|
||||
#if HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI)
|
||||
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
|
||||
|
||||
if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) {
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
|
||||
@@ -400,7 +403,9 @@ void PowerFSM_setup()
|
||||
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
|
||||
NULL, "Screen-on timeout");
|
||||
}
|
||||
#else
|
||||
#endif // HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI)
|
||||
|
||||
#else // (not) ARCH_ESP32
|
||||
// If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
|
||||
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
@@ -409,4 +414,4 @@ void PowerFSM_setup()
|
||||
|
||||
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -570,6 +570,19 @@ bool GPS::setup()
|
||||
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
|
||||
_serial_gps->write("$PMTK886,1*29\r\n");
|
||||
delay(250);
|
||||
} else if (gnssModel == GNSS_MODEL_MTK_PA1010D) {
|
||||
// PA1010D is used in the Pimoroni GPS board.
|
||||
|
||||
// Enable all constellations.
|
||||
_serial_gps->write("$PMTK353,1,1,1,1,1*2A\r\n");
|
||||
// Above command will reset the GPS and takes longer before it will accept new commands
|
||||
delay(1000);
|
||||
// Only ask for RMC and GGA (GNRMC and GNGGA)
|
||||
_serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
|
||||
delay(250);
|
||||
// Enable SBAS / WAAS
|
||||
_serial_gps->write("$PMTK301,2*2E\r\n");
|
||||
delay(250);
|
||||
} else if (gnssModel == GNSS_MODEL_MTK_PA1616S) {
|
||||
// PA1616S is used in some GPS breakout boards from Adafruit
|
||||
// PA1616S does not have GLONASS capability. PA1616D does, but is not implemented here.
|
||||
@@ -810,13 +823,6 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
powerState = newState;
|
||||
LOG_INFO("GPS power state move from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
|
||||
|
||||
#ifdef HELTEC_MESH_NODE_T114
|
||||
if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) {
|
||||
_serial_gps->begin(serialSpeeds[speedSelect]);
|
||||
} else if ((newState == GPS_OFF || newState == GPS_HARDSLEEP) && (oldState != GPS_OFF && oldState != GPS_HARDSLEEP)) {
|
||||
_serial_gps->end();
|
||||
}
|
||||
#endif
|
||||
switch (newState) {
|
||||
case GPS_ACTIVE:
|
||||
case GPS_IDLE:
|
||||
@@ -1245,9 +1251,11 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
|
||||
delay(20);
|
||||
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
|
||||
{"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D},
|
||||
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
|
||||
{"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B},
|
||||
{"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}};
|
||||
|
||||
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
|
||||
|
||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef enum {
|
||||
GNSS_MODEL_UC6580,
|
||||
GNSS_MODEL_UNKNOWN,
|
||||
GNSS_MODEL_MTK_L76B,
|
||||
GNSS_MODEL_MTK_PA1010D,
|
||||
GNSS_MODEL_MTK_PA1616S,
|
||||
GNSS_MODEL_AG3335,
|
||||
GNSS_MODEL_AG3352,
|
||||
|
||||
@@ -181,7 +181,6 @@ bool EInkDisplay::connect()
|
||||
// Start HSPI
|
||||
hspi = new SPIClass(HSPI);
|
||||
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
|
||||
|
||||
// VExt already enabled in setup()
|
||||
// RTC GPIO hold disabled in setup()
|
||||
|
||||
@@ -218,6 +217,21 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->setRotation(1);
|
||||
adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT);
|
||||
}
|
||||
#elif defined(HELTEC_MESH_POCKET)
|
||||
{
|
||||
spi1 = &SPI1;
|
||||
spi1->begin();
|
||||
// VExt already enabled in setup()
|
||||
// RTC GPIO hold disabled in setup()
|
||||
|
||||
// Create GxEPD2 objects
|
||||
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *spi1);
|
||||
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
|
||||
// Init GxEPD2
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
@@ -73,6 +73,10 @@ class EInkDisplay : public OLEDDisplay
|
||||
SPIClass *hspi = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HELTEC_MESH_POCKET)
|
||||
SPIClass *spi1 = NULL;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// FIXME quick hack to limit drawing to a very slow rate
|
||||
uint32_t lastDrawMsec = 0;
|
||||
|
||||
@@ -1104,7 +1104,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
|
||||
char usersString[20];
|
||||
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||
#else
|
||||
@@ -1545,7 +1545,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \
|
||||
defined(RAK14014) || defined(HX8357_CS)
|
||||
defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS)
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
|
||||
@@ -1751,7 +1751,7 @@ void Screen::setup()
|
||||
// flip it. If you have a headache now, you're welcome.
|
||||
if (!config.display.flip_screen) {
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
|
||||
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
|
||||
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS)
|
||||
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
|
||||
#elif defined(USE_ST7789)
|
||||
static_cast<ST7789Spi *>(dispdev)->flipScreenVertically();
|
||||
@@ -1796,7 +1796,9 @@ void Screen::setup()
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
|
||||
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
||||
#if !MESHTASTIC_EXCLUDE_ADMIN
|
||||
adminMessageObserver.observe(adminModule);
|
||||
#endif
|
||||
if (textMessageModule)
|
||||
textMessageObserver.observe(textMessageModule);
|
||||
if (inputBroker)
|
||||
@@ -2490,7 +2492,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
|
||||
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgQuestionL1);
|
||||
@@ -2502,7 +2504,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
|
||||
imgSFL1);
|
||||
@@ -2517,7 +2519,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
} else {
|
||||
// TODO: Raspberry Pi supports more than just the one screen size
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgInfoL1);
|
||||
@@ -2838,9 +2840,6 @@ int Screen::handleInputEvent(const InputEvent *event)
|
||||
|
||||
int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
|
||||
{
|
||||
// Note: only selected admin messages notify this observer
|
||||
// If you wish to handle a new type of message, you should modify AdminModule.cpp first
|
||||
|
||||
switch (arg->which_payload_variant) {
|
||||
// Node removed manually (i.e. via app)
|
||||
case meshtastic_AdminMessage_remove_by_nodenum_tag:
|
||||
@@ -2857,4 +2856,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
|
||||
} // namespace graphics
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
#endif // HAS_SCREEN
|
||||
#endif // HAS_SCREEN
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) || \
|
||||
defined(ILI9488_CS) && !defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
|
||||
#define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28
|
||||
|
||||
@@ -120,6 +120,303 @@ static void rak14014_tpIntHandle(void)
|
||||
_rak14014_touch_int = true;
|
||||
}
|
||||
|
||||
#elif defined(ST72xx_DE)
|
||||
#include <LovyanGFX.hpp>
|
||||
#include <TCA9534.h>
|
||||
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
|
||||
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
|
||||
TCA9534 ioex;
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Bus_RGB _bus_instance;
|
||||
lgfx::Panel_RGB _panel_instance;
|
||||
lgfx::Touch_GT911 _touch_instance;
|
||||
|
||||
public:
|
||||
const uint16_t screenWidth = TFT_WIDTH;
|
||||
const uint16_t screenHeight = TFT_HEIGHT;
|
||||
|
||||
bool init_impl(bool use_reset, bool use_clear) override
|
||||
{
|
||||
ioex.attach(Wire);
|
||||
ioex.setDeviceAddress(0x18);
|
||||
ioex.config(1, TCA9534::Config::OUT);
|
||||
ioex.config(2, TCA9534::Config::OUT);
|
||||
ioex.config(3, TCA9534::Config::OUT);
|
||||
ioex.config(4, TCA9534::Config::OUT);
|
||||
|
||||
ioex.output(1, TCA9534::Level::H);
|
||||
ioex.output(3, TCA9534::Level::L);
|
||||
ioex.output(4, TCA9534::Level::H);
|
||||
|
||||
pinMode(1, OUTPUT);
|
||||
digitalWrite(1, LOW);
|
||||
ioex.output(2, TCA9534::Level::L);
|
||||
delay(20);
|
||||
ioex.output(2, TCA9534::Level::H);
|
||||
delay(100);
|
||||
pinMode(1, INPUT);
|
||||
|
||||
return LGFX_Device::init_impl(use_reset, use_clear);
|
||||
}
|
||||
|
||||
LGFX(void)
|
||||
{
|
||||
{
|
||||
auto cfg = _panel_instance.config();
|
||||
|
||||
cfg.memory_width = screenWidth;
|
||||
cfg.memory_height = screenHeight;
|
||||
cfg.panel_width = screenWidth;
|
||||
cfg.panel_height = screenHeight;
|
||||
cfg.offset_x = 0;
|
||||
cfg.offset_y = 0;
|
||||
cfg.offset_rotation = 0;
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
{
|
||||
auto cfg = _panel_instance.config_detail();
|
||||
cfg.use_psram = 0;
|
||||
_panel_instance.config_detail(cfg);
|
||||
}
|
||||
|
||||
{
|
||||
auto cfg = _bus_instance.config();
|
||||
cfg.panel = &_panel_instance;
|
||||
cfg.pin_d0 = ST72xx_B0; // B0
|
||||
cfg.pin_d1 = ST72xx_B1; // B1
|
||||
cfg.pin_d2 = ST72xx_B2; // B2
|
||||
cfg.pin_d3 = ST72xx_B3; // B3
|
||||
cfg.pin_d4 = ST72xx_B4; // B4
|
||||
cfg.pin_d5 = ST72xx_G0; // G0
|
||||
cfg.pin_d6 = ST72xx_G1; // G1
|
||||
cfg.pin_d7 = ST72xx_G2; // G2
|
||||
cfg.pin_d8 = ST72xx_G3; // G3
|
||||
cfg.pin_d9 = ST72xx_G4; // G4
|
||||
cfg.pin_d10 = ST72xx_G5; // G5
|
||||
cfg.pin_d11 = ST72xx_R0; // R0
|
||||
cfg.pin_d12 = ST72xx_R1; // R1
|
||||
cfg.pin_d13 = ST72xx_R2; // R2
|
||||
cfg.pin_d14 = ST72xx_R3; // R3
|
||||
cfg.pin_d15 = ST72xx_R4; // R4
|
||||
|
||||
cfg.pin_henable = ST72xx_DE;
|
||||
cfg.pin_vsync = ST72xx_VSYNC;
|
||||
cfg.pin_hsync = ST72xx_HSYNC;
|
||||
cfg.pin_pclk = ST72xx_PCLK;
|
||||
cfg.freq_write = 13000000;
|
||||
|
||||
#ifdef ST7265_HSYNC_POLARITY
|
||||
cfg.hsync_polarity = ST7265_HSYNC_POLARITY;
|
||||
cfg.hsync_front_porch = ST7265_HSYNC_FRONT_PORCH; // 8;
|
||||
cfg.hsync_pulse_width = ST7265_HSYNC_PULSE_WIDTH; // 4;
|
||||
cfg.hsync_back_porch = ST7265_HSYNC_BACK_PORCH; // 8;
|
||||
|
||||
cfg.vsync_polarity = ST7265_VSYNC_POLARITY; // 0;
|
||||
cfg.vsync_front_porch = ST7265_VSYNC_FRONT_PORCH; // 8;
|
||||
cfg.vsync_pulse_width = ST7265_VSYNC_PULSE_WIDTH; // 4;
|
||||
cfg.vsync_back_porch = ST7265_VSYNC_BACK_PORCH; // 8;
|
||||
|
||||
cfg.pclk_idle_high = 1;
|
||||
cfg.pclk_active_neg = ST7265_PCLK_ACTIVE_NEG; // 0;
|
||||
// cfg.pclk_idle_high = 0;
|
||||
// cfg.de_idle_high = 1;
|
||||
#endif
|
||||
|
||||
#ifdef ST7262_HSYNC_POLARITY
|
||||
cfg.hsync_polarity = ST7262_HSYNC_POLARITY;
|
||||
cfg.hsync_front_porch = ST7262_HSYNC_FRONT_PORCH; // 8;
|
||||
cfg.hsync_pulse_width = ST7262_HSYNC_PULSE_WIDTH; // 4;
|
||||
cfg.hsync_back_porch = ST7262_HSYNC_BACK_PORCH; // 8;
|
||||
|
||||
cfg.vsync_polarity = ST7262_VSYNC_POLARITY; // 0;
|
||||
cfg.vsync_front_porch = ST7262_VSYNC_FRONT_PORCH; // 8;
|
||||
cfg.vsync_pulse_width = ST7262_VSYNC_PULSE_WIDTH; // 4;
|
||||
cfg.vsync_back_porch = ST7262_VSYNC_BACK_PORCH; // 8;
|
||||
|
||||
cfg.pclk_idle_high = 1;
|
||||
cfg.pclk_active_neg = ST7262_PCLK_ACTIVE_NEG; // 0;
|
||||
// cfg.pclk_idle_high = 0;
|
||||
// cfg.de_idle_high = 1;
|
||||
#endif
|
||||
|
||||
#ifdef SC7277_HSYNC_POLARITY
|
||||
cfg.hsync_polarity = SC7277_HSYNC_POLARITY;
|
||||
cfg.hsync_front_porch = SC7277_HSYNC_FRONT_PORCH; // 8;
|
||||
cfg.hsync_pulse_width = SC7277_HSYNC_PULSE_WIDTH; // 4;
|
||||
cfg.hsync_back_porch = SC7277_HSYNC_BACK_PORCH; // 8;
|
||||
|
||||
cfg.vsync_polarity = SC7277_VSYNC_POLARITY; // 0;
|
||||
cfg.vsync_front_porch = SC7277_VSYNC_FRONT_PORCH; // 8;
|
||||
cfg.vsync_pulse_width = SC7277_VSYNC_PULSE_WIDTH; // 4;
|
||||
cfg.vsync_back_porch = SC7277_VSYNC_BACK_PORCH; // 8;
|
||||
|
||||
cfg.pclk_idle_high = 1;
|
||||
cfg.pclk_active_neg = SC7277_PCLK_ACTIVE_NEG; // 0;
|
||||
// cfg.pclk_idle_high = 0;
|
||||
// cfg.de_idle_high = 1;
|
||||
#endif
|
||||
|
||||
_bus_instance.config(cfg);
|
||||
}
|
||||
_panel_instance.setBus(&_bus_instance);
|
||||
|
||||
{
|
||||
auto cfg = _touch_instance.config();
|
||||
cfg.x_min = 0;
|
||||
cfg.x_max = TFT_WIDTH;
|
||||
cfg.y_min = 0;
|
||||
cfg.y_max = TFT_HEIGHT;
|
||||
cfg.pin_int = -1;
|
||||
cfg.pin_rst = -1;
|
||||
cfg.bus_shared = true;
|
||||
cfg.offset_rotation = 0;
|
||||
|
||||
cfg.i2c_port = 0;
|
||||
cfg.i2c_addr = 0x5D;
|
||||
cfg.pin_sda = I2C_SDA;
|
||||
cfg.pin_scl = I2C_SCL;
|
||||
cfg.freq = 400000;
|
||||
_touch_instance.config(cfg);
|
||||
_panel_instance.setTouch(&_touch_instance);
|
||||
}
|
||||
|
||||
setPanel(&_panel_instance);
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ILI9488_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ILI9488 driver chip
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_ILI9488 _panel_instance;
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
lgfx::Light_PWM _light_instance;
|
||||
lgfx::Touch_GT911 _touch_instance;
|
||||
|
||||
public:
|
||||
LGFX(void)
|
||||
{
|
||||
{
|
||||
auto cfg = _bus_instance.config();
|
||||
|
||||
// configure SPI
|
||||
cfg.spi_host = ILI9488_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
|
||||
cfg.spi_mode = 0;
|
||||
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
|
||||
// 80MHz by an integer)
|
||||
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
|
||||
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
|
||||
cfg.use_lock = true; // Set to true to use transaction locking
|
||||
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
|
||||
// SPI_DMA_CH_AUTO=auto setting)
|
||||
cfg.pin_sclk = ILI9488_SCK; // Set SPI SCLK pin number
|
||||
cfg.pin_mosi = ILI9488_SDA; // Set SPI MOSI pin number
|
||||
cfg.pin_miso = ILI9488_MISO; // Set SPI MISO pin number (-1 = disable)
|
||||
cfg.pin_dc = ILI9488_RS; // Set SPI DC pin number (-1 = disable)
|
||||
|
||||
_bus_instance.config(cfg); // applies the set value to the bus.
|
||||
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
|
||||
}
|
||||
|
||||
{ // Set the display panel control.
|
||||
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
|
||||
|
||||
cfg.pin_cs = ILI9488_CS; // Pin number where CS is connected (-1 = disable)
|
||||
cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable)
|
||||
cfg.pin_busy = -1; // Pin number where BUSY is connected (-1 = disable)
|
||||
|
||||
// The following setting values are general initial values for each panel, so please comment out any
|
||||
// unknown items and try them.
|
||||
|
||||
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
|
||||
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
|
||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
#ifdef TFT_DUMMY_READ_PIXELS
|
||||
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
|
||||
#else
|
||||
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
||||
#endif
|
||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||
cfg.readable = true; // Set to true if data can be read
|
||||
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||
cfg.dlen_16bit =
|
||||
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
|
||||
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
|
||||
|
||||
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
|
||||
// ST7735 or ILI9163.
|
||||
// cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
|
||||
// cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
#ifdef ILI9488_BL
|
||||
// Set the backlight control
|
||||
{
|
||||
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||
|
||||
cfg.pin_bl = ILI9488_BL; // Pin number to which the backlight is connected
|
||||
cfg.invert = false; // true to invert the brightness of the backlight
|
||||
// cfg.freq = 44100; // PWM frequency of backlight
|
||||
// cfg.pwm_channel = 1; // PWM channel number to use
|
||||
|
||||
_light_instance.config(cfg);
|
||||
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_TOUCHSCREEN
|
||||
// Configure settings for touch screen control.
|
||||
{
|
||||
auto cfg = _touch_instance.config();
|
||||
|
||||
cfg.pin_cs = -1;
|
||||
cfg.x_min = 0;
|
||||
cfg.x_max = TFT_HEIGHT - 1;
|
||||
cfg.y_min = 0;
|
||||
cfg.y_max = TFT_WIDTH - 1;
|
||||
cfg.pin_int = SCREEN_TOUCH_INT;
|
||||
#ifdef SCREEN_TOUCH_RST
|
||||
cfg.pin_rst = SCREEN_TOUCH_RST;
|
||||
#endif
|
||||
cfg.bus_shared = true;
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION;
|
||||
// cfg.freq = 2500000;
|
||||
|
||||
// I2C
|
||||
cfg.i2c_port = TOUCH_I2C_PORT;
|
||||
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
|
||||
#ifdef SCREEN_TOUCH_USE_I2C1
|
||||
cfg.pin_sda = I2C_SDA1;
|
||||
cfg.pin_scl = I2C_SCL1;
|
||||
#else
|
||||
cfg.pin_sda = I2C_SDA;
|
||||
cfg.pin_scl = I2C_SCL;
|
||||
#endif
|
||||
// cfg.freq = 400000;
|
||||
|
||||
_touch_instance.config(cfg);
|
||||
_panel_instance.setTouch(&_touch_instance);
|
||||
}
|
||||
#endif
|
||||
|
||||
setPanel(&_panel_instance);
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ST7789_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
|
||||
@@ -129,7 +426,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
lgfx::Light_PWM _light_instance;
|
||||
#if HAS_TOUCHSCREEN
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(ELECROW)
|
||||
lgfx::Touch_FT5x06 _touch_instance;
|
||||
#else
|
||||
lgfx::Touch_GT911 _touch_instance;
|
||||
@@ -171,16 +468,22 @@ class LGFX : public lgfx::LGFX_Device
|
||||
// The following setting values are general initial values for each panel, so please comment out any
|
||||
// unknown items and try them.
|
||||
|
||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||
cfg.readable = true; // Set to true if data can be read
|
||||
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
|
||||
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
|
||||
cfg.panel_width = TFT_WIDTH; // actual displayable width
|
||||
cfg.panel_height = TFT_HEIGHT; // actual displayable height
|
||||
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
|
||||
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
#ifdef TFT_DUMMY_READ_PIXELS
|
||||
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
|
||||
#else
|
||||
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
|
||||
#endif
|
||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||
cfg.readable = true; // Set to true if data can be read
|
||||
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||
cfg.dlen_16bit =
|
||||
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
|
||||
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
|
||||
@@ -217,6 +520,9 @@ class LGFX : public lgfx::LGFX_Device
|
||||
cfg.y_min = 0;
|
||||
cfg.y_max = TFT_WIDTH - 1;
|
||||
cfg.pin_int = SCREEN_TOUCH_INT;
|
||||
#ifdef SCREEN_TOUCH_RST
|
||||
cfg.pin_rst = SCREEN_TOUCH_RST;
|
||||
#endif
|
||||
cfg.bus_shared = true;
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION;
|
||||
// cfg.freq = 2500000;
|
||||
@@ -640,7 +946,7 @@ static LGFX *tft = nullptr;
|
||||
#endif
|
||||
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||
defined(RAK14014) || defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
|
||||
defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
|
||||
#include "SPILock.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -21,7 +21,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
|
||||
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "./DEPG0154BNS800.h"
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
|
||||
E-Ink display driver
|
||||
- DEPG0154BNS800
|
||||
- Manufacturer: DKE
|
||||
- Size: 1.54 inch
|
||||
- Resolution: 152px x 152px
|
||||
- Flex connector marking: FPC7525
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
#include "configuration.h"
|
||||
|
||||
#include "./SSD16XX.h"
|
||||
|
||||
namespace NicheGraphics::Drivers
|
||||
{
|
||||
class DEPG0154BNS800 : public SSD16XX
|
||||
{
|
||||
// Display properties
|
||||
private:
|
||||
static constexpr uint32_t width = 152;
|
||||
static constexpr uint32_t height = 152;
|
||||
static constexpr UpdateTypes supported = (UpdateTypes)(FULL);
|
||||
|
||||
public:
|
||||
DEPG0154BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::Drivers
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
132
src/graphics/niche/Drivers/EInk/DEPG0213BNS800.cpp
Normal file
132
src/graphics/niche/Drivers/EInk/DEPG0213BNS800.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "./DEPG0213BNS800.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
using namespace NicheGraphics::Drivers;
|
||||
|
||||
// Describes the operation performed when a "fast refresh" is performed
|
||||
// Source: Modified from GxEPD2 (GxEPD2_213_BN)
|
||||
static const uint8_t LUT_FAST[] = {
|
||||
// 1 2 3
|
||||
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2B (Existing black pixels)
|
||||
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2W (New white pixels)
|
||||
0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2B (New black pixels)
|
||||
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2W (Existing white pixels)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VCOM
|
||||
|
||||
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 1. Any pixels changing W2B or B2W. Two medium taps.
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2. All pixels. One short tap.
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3. Cooldown
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, //
|
||||
};
|
||||
|
||||
// How strongly the pixels are pulled and pushed
|
||||
void DEPG0213BNS800::configVoltages()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
// Reference: display datasheet, GxEPD1
|
||||
sendCommand(0x03); // Gate voltage
|
||||
sendData(0x17); // VGH: 20V
|
||||
|
||||
// Reference: display datasheet, GxEPD1
|
||||
sendCommand(0x04); // Source voltage
|
||||
sendData(0x41); // VSH1: 15V
|
||||
sendData(0x00); // VSH2: NA
|
||||
sendData(0x32); // VSL: -15V
|
||||
|
||||
// GxEPD1 sets this at -1.2V, but that seems to be drive the pixels very hard
|
||||
sendCommand(0x2C); // VCOM voltage
|
||||
sendData(0x08); // VCOM: -0.2V
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
// From OTP memory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load settings about how the pixels are moved from old state to new state during a refresh
|
||||
// - manually specified,
|
||||
// - or with stored values from displays OTP memory
|
||||
void DEPG0213BNS800::configWaveform()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
sendCommand(0x3C); // Border waveform:
|
||||
sendData(0x80); // VSS
|
||||
|
||||
sendCommand(0x32); // Write LUT register from MCU:
|
||||
sendData(LUT_FAST, sizeof(LUT_FAST)); // (describes operation for a FAST refresh)
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
// From OTP memory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Describes the sequence of events performed by the displays controller IC during a refresh
|
||||
// Includes "power up", "load settings from memory", "update the pixels", etc
|
||||
void DEPG0213BNS800::configUpdateSequence()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xCF); // Differential, use manually loaded waveform
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xF7); // Non-differential, load waveform from OTP
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Once the refresh operation has been started,
|
||||
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
|
||||
// Only used when refresh is "async"
|
||||
void DEPG0213BNS800::detachFromUpdate()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
return beginPolling(50, 500); // At least 500ms, then poll every 50ms
|
||||
case FULL:
|
||||
default:
|
||||
return beginPolling(100, 3500); // At least 3500ms, then poll every 100ms
|
||||
}
|
||||
}
|
||||
|
||||
// For this display, we do not need to re-write the new image.
|
||||
// We're overriding SSD16XX::finalizeUpdate to make this small optimization.
|
||||
// The display does also work just fine with the generic SSD16XX method, though.
|
||||
void DEPG0213BNS800::finalizeUpdate()
|
||||
{
|
||||
// Put a copy of the image into the "old memory".
|
||||
// Used with differential refreshes (e.g. FAST update), to determine which px need to move, and which can remain in place
|
||||
// We need to keep the "old memory" up to date, because don't know whether next refresh will be FULL or FAST etc.
|
||||
if (updateType != FULL) {
|
||||
// writeNewImage(); // Not required for this display
|
||||
writeOldImage();
|
||||
sendCommand(0x7F); // Terminate image write without update
|
||||
wait();
|
||||
}
|
||||
|
||||
// Enter deep-sleep to save a few µA
|
||||
// Waking from this requires that display's reset pin is broken out
|
||||
if (pin_rst != 0xFF)
|
||||
deepSleep();
|
||||
}
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
44
src/graphics/niche/Drivers/EInk/DEPG0213BNS800.h
Normal file
44
src/graphics/niche/Drivers/EInk/DEPG0213BNS800.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
E-Ink display driver
|
||||
- DEPG0213BNS800
|
||||
- Manufacturer: DKE
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 122px x 250px
|
||||
- Flex connector marking: FPC-7528B
|
||||
|
||||
Note: this is from an older generation of DKE panels, which still used Solomon Systech controller ICs.
|
||||
DKE's website suggests that the latest DEPG0213BN displays may use Fitipower controllers instead.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "./SSD16XX.h"
|
||||
|
||||
namespace NicheGraphics::Drivers
|
||||
{
|
||||
class DEPG0213BNS800 : public SSD16XX
|
||||
{
|
||||
// Display properties
|
||||
private:
|
||||
static constexpr uint32_t width = 122;
|
||||
static constexpr uint32_t height = 250;
|
||||
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
|
||||
|
||||
public:
|
||||
DEPG0213BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
|
||||
|
||||
protected:
|
||||
void configVoltages() override;
|
||||
void configWaveform() override;
|
||||
void configUpdateSequence() override;
|
||||
void detachFromUpdate() override;
|
||||
void finalizeUpdate() override; // Only overriden for a slight optimization
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::Drivers
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
@@ -116,5 +116,10 @@ void DEPG0290BNS800::finalizeUpdate()
|
||||
sendCommand(0x7F); // Terminate image write without update
|
||||
wait();
|
||||
}
|
||||
|
||||
// Enter deep-sleep to save a few µA
|
||||
// Waking from this requires that display's reset pin is broken out
|
||||
if (pin_rst != 0xFF)
|
||||
deepSleep();
|
||||
}
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
68
src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp
Normal file
68
src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "./LCMEN2R13ECC1.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
using namespace NicheGraphics::Drivers;
|
||||
|
||||
// Map the display controller IC's output to the connected panel
|
||||
void LCMEN2R13ECC1::configScanning()
|
||||
{
|
||||
// "Driver output control"
|
||||
sendCommand(0x01);
|
||||
sendData(0xF9);
|
||||
sendData(0x00);
|
||||
sendData(0x00);
|
||||
|
||||
// To-do: delete this method?
|
||||
// Values set here might be redundant: F9, 00, 00 seems to be default
|
||||
}
|
||||
|
||||
// Specify which information is used to control the sequence of voltages applied to move the pixels
|
||||
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
|
||||
// the controller IC's OTP memory, when the update procedure begins.
|
||||
void LCMEN2R13ECC1::configWaveform()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
sendCommand(0x3C); // Border waveform:
|
||||
sendData(0x85);
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
// From OTP memory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LCMEN2R13ECC1::configUpdateSequence()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
|
||||
break;
|
||||
|
||||
case FULL:
|
||||
default:
|
||||
sendCommand(0x22); // Set "update sequence"
|
||||
sendData(0xF7); // Will load LUT from OTP memory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Once the refresh operation has been started,
|
||||
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
|
||||
// Only used when refresh is "async"
|
||||
void LCMEN2R13ECC1::detachFromUpdate()
|
||||
{
|
||||
switch (updateType) {
|
||||
case FAST:
|
||||
return beginPolling(50, 800); // At least 500ms for fast refresh
|
||||
case FULL:
|
||||
default:
|
||||
return beginPolling(100, 2500); // At least 2 seconds for full refresh
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
41
src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h
Normal file
41
src/graphics/niche/Drivers/EInk/LCMEN2R13ECC1.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
E-Ink display driver
|
||||
- SSD1680
|
||||
- Manufacturer: WISEVAST
|
||||
- Size: 2.13 inch
|
||||
- Resolution: 122px x 255px
|
||||
- Flex connector marking: Soldering connector, no connector is needed
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "./SSD16XX.h"
|
||||
|
||||
namespace NicheGraphics::Drivers
|
||||
{
|
||||
class LCMEN2R13ECC1 : public SSD16XX
|
||||
{
|
||||
// Display properties
|
||||
private:
|
||||
static constexpr uint32_t width = 122;
|
||||
static constexpr uint32_t height = 250;
|
||||
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
|
||||
|
||||
public:
|
||||
LCMEN2R13ECC1() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
|
||||
|
||||
protected:
|
||||
virtual void configScanning() override;
|
||||
virtual void configWaveform() override;
|
||||
virtual void configUpdateSequence() override;
|
||||
void detachFromUpdate() override;
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::Drivers
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "./LCMEN2R13EFC1.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "./LCMEN2R13EFC1.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "SPILock.h"
|
||||
|
||||
using namespace NicheGraphics::Drivers;
|
||||
|
||||
// Look up table: fast refresh, common electrode
|
||||
@@ -42,11 +44,10 @@ static const uint8_t LUT_FAST_BW[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
};
|
||||
|
||||
// Look up table: fash refresh, pixels which change from white to black
|
||||
// Look up table: fast refresh, pixels which change from white to black
|
||||
static const uint8_t LUT_FAST_WB[] = {
|
||||
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
|
||||
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
|
||||
0x01, 0x46, 0x43, 0x02, 0x01, 0x01, 0x01, //
|
||||
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
@@ -55,7 +56,7 @@ static const uint8_t LUT_FAST_WB[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
||||
};
|
||||
|
||||
// Look up table: fash refresh, pixels which remain black
|
||||
// Look up table: fast refresh, pixels which remain black
|
||||
static const uint8_t LUT_FAST_BB[] = {
|
||||
0x01, 0x06, 0x03, 0x42, 0x41, 0x01, 0x01, //
|
||||
0x01, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, //
|
||||
@@ -151,6 +152,9 @@ void LCMEN213EFC1::reset()
|
||||
|
||||
void LCMEN213EFC1::sendCommand(const uint8_t command)
|
||||
{
|
||||
// Take firmware's SPI lock
|
||||
spiLock->lock();
|
||||
|
||||
spi->beginTransaction(spiSettings);
|
||||
digitalWrite(pin_dc, LOW); // DC pin low indicates command
|
||||
digitalWrite(pin_cs, LOW);
|
||||
@@ -158,6 +162,8 @@ void LCMEN213EFC1::sendCommand(const uint8_t command)
|
||||
digitalWrite(pin_cs, HIGH);
|
||||
digitalWrite(pin_dc, HIGH);
|
||||
spi->endTransaction();
|
||||
|
||||
spiLock->unlock();
|
||||
}
|
||||
|
||||
void LCMEN213EFC1::sendData(uint8_t data)
|
||||
@@ -167,6 +173,9 @@ void LCMEN213EFC1::sendData(uint8_t data)
|
||||
|
||||
void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
|
||||
{
|
||||
// Take firmware's SPI lock
|
||||
spiLock->lock();
|
||||
|
||||
spi->beginTransaction(spiSettings);
|
||||
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
|
||||
digitalWrite(pin_cs, LOW);
|
||||
@@ -184,6 +193,8 @@ void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
|
||||
digitalWrite(pin_cs, HIGH);
|
||||
digitalWrite(pin_dc, HIGH);
|
||||
spi->endTransaction();
|
||||
|
||||
spiLock->unlock();
|
||||
}
|
||||
|
||||
void LCMEN213EFC1::configFull()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
|
||||
#include "./SSD16XX.h"
|
||||
|
||||
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
#include "SPILock.h"
|
||||
|
||||
using namespace NicheGraphics::Drivers;
|
||||
|
||||
SSD16XX::SSD16XX(uint16_t width, uint16_t height, UpdateTypes supported, uint8_t bufferOffsetX)
|
||||
@@ -82,6 +85,9 @@ void SSD16XX::sendCommand(const uint8_t command)
|
||||
if (failed)
|
||||
return;
|
||||
|
||||
// Take firmware's SPI lock
|
||||
spiLock->lock();
|
||||
|
||||
spi->beginTransaction(spiSettings);
|
||||
digitalWrite(pin_dc, LOW); // DC pin low indicates command
|
||||
digitalWrite(pin_cs, LOW);
|
||||
@@ -89,6 +95,8 @@ void SSD16XX::sendCommand(const uint8_t command)
|
||||
digitalWrite(pin_cs, HIGH);
|
||||
digitalWrite(pin_dc, HIGH);
|
||||
spi->endTransaction();
|
||||
|
||||
spiLock->unlock();
|
||||
}
|
||||
|
||||
void SSD16XX::sendData(uint8_t data)
|
||||
@@ -103,6 +111,9 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
|
||||
if (failed)
|
||||
return;
|
||||
|
||||
// Take firmware's SPI lock
|
||||
spiLock->lock();
|
||||
|
||||
spi->beginTransaction(spiSettings);
|
||||
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
|
||||
digitalWrite(pin_cs, LOW);
|
||||
@@ -119,6 +130,8 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
|
||||
digitalWrite(pin_cs, HIGH);
|
||||
digitalWrite(pin_dc, HIGH);
|
||||
spi->endTransaction();
|
||||
|
||||
spiLock->unlock();
|
||||
}
|
||||
|
||||
void SSD16XX::configFullscreen()
|
||||
@@ -242,5 +255,18 @@ void SSD16XX::finalizeUpdate()
|
||||
sendCommand(0x7F); // Terminate image write without update
|
||||
wait();
|
||||
}
|
||||
|
||||
// Enter deep-sleep to save a few µA
|
||||
// Waking from this requires that display's reset pin is broken out
|
||||
if (pin_rst != 0xFF)
|
||||
deepSleep();
|
||||
}
|
||||
|
||||
// Enter a lower-power state
|
||||
// May only save a few µA..
|
||||
void SSD16XX::deepSleep()
|
||||
{
|
||||
sendCommand(0x10); // Enter deep sleep
|
||||
sendData(0x01); // Mode 1: preserve image RAM
|
||||
}
|
||||
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
||||
@@ -44,6 +44,7 @@ class SSD16XX : public EInk
|
||||
virtual void detachFromUpdate();
|
||||
virtual bool isUpdateDone() override;
|
||||
virtual void finalizeUpdate() override;
|
||||
virtual void deepSleep();
|
||||
|
||||
protected:
|
||||
uint8_t bufferOffsetX = 0; // In bytes. Panel x=0 does not always align with controller x=0. Quirky internal wiring?
|
||||
|
||||
@@ -13,6 +13,7 @@ Avoid bloating everyone's protobuf code for our one-off UI implementations
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "SPILock.h"
|
||||
#include "SafeFile.h"
|
||||
|
||||
namespace NicheGraphics
|
||||
@@ -46,6 +47,9 @@ template <typename T> class FlashData
|
||||
public:
|
||||
static bool load(T *data, const char *label)
|
||||
{
|
||||
// Take firmware's SPI lock
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
|
||||
// Set false if we run into issues
|
||||
bool okay = true;
|
||||
|
||||
@@ -103,14 +107,18 @@ template <typename T> class FlashData
|
||||
return okay;
|
||||
}
|
||||
|
||||
// Save module's custom data (settings?) to flash. Does use protobufs
|
||||
// Save module's custom data (settings?) to flash. Doesn't use protobufs
|
||||
// Takes the firmware's SPI lock, in case the files are stored on SD card
|
||||
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally.
|
||||
static void save(T *data, const char *label)
|
||||
{
|
||||
// Get a filename based on the label
|
||||
std::string filename = getFilename(label);
|
||||
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/NicheGraphics");
|
||||
spiLock->unlock();
|
||||
|
||||
auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename.
|
||||
|
||||
@@ -119,10 +127,10 @@ template <typename T> class FlashData
|
||||
// Calculate a hash of the data
|
||||
uint32_t hash = getHash(data);
|
||||
|
||||
spiLock->lock();
|
||||
f.write((uint8_t *)data, sizeof(T)); // Write the actual data
|
||||
f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash
|
||||
|
||||
// f.flush();
|
||||
spiLock->unlock();
|
||||
|
||||
bool writeSucceeded = f.close();
|
||||
|
||||
@@ -135,6 +143,32 @@ template <typename T> class FlashData
|
||||
}
|
||||
};
|
||||
|
||||
// Erase contents of the NicheGraphics data directory
|
||||
inline void clearFlashData()
|
||||
{
|
||||
|
||||
// Take firmware's SPI lock, in case the files are stored on SD card
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
|
||||
#ifdef FSCom
|
||||
File dir = FSCom.open("/NicheGraphics"); // Open the directory
|
||||
File file = dir.openNextFile(); // Attempt to open the first file in the directory
|
||||
|
||||
// While the directory still contains files
|
||||
while (file) {
|
||||
std::string path = "/NicheGraphics/";
|
||||
path += file.name();
|
||||
LOG_DEBUG("Erasing %s", path.c_str());
|
||||
file.close();
|
||||
FSCom.remove(path.c_str());
|
||||
|
||||
file = dir.openNextFile();
|
||||
}
|
||||
#else
|
||||
LOG_ERROR("ERROR: Filesystem not implemented\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace NicheGraphics
|
||||
|
||||
#endif
|
||||
@@ -11,10 +11,19 @@ InkHUD::LogoApplet::LogoApplet() : concurrency::OSThread("LogoApplet")
|
||||
OSThread::setIntervalFromNow(8 * 1000UL);
|
||||
OSThread::enabled = true;
|
||||
|
||||
textLeft = "";
|
||||
textRight = "";
|
||||
textTitle = xstr(APP_VERSION_SHORT);
|
||||
fontTitle = fontSmall;
|
||||
// During onboarding, show the default short name as well as the version string
|
||||
// This behavior assists manufacturers during mass production, and should not be modified without good reason
|
||||
if (!settings->tips.safeShutdownSeen) {
|
||||
fontTitle = fontLarge;
|
||||
textLeft = xstr(APP_VERSION_SHORT);
|
||||
textRight = owner.short_name;
|
||||
textTitle = "Meshtastic";
|
||||
} else {
|
||||
fontTitle = fontSmall;
|
||||
textLeft = "";
|
||||
textRight = "";
|
||||
textTitle = xstr(APP_VERSION_SHORT);
|
||||
}
|
||||
|
||||
bringToForeground();
|
||||
// This is then drawn with a FULL refresh by Renderer::begin
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#include "./Events.h"
|
||||
|
||||
#include "RTC.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "sleep.h"
|
||||
|
||||
#include "./Applet.h"
|
||||
#include "./SystemApplet.h"
|
||||
#include "graphics/niche/FlashData.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
@@ -25,6 +27,9 @@ void InkHUD::Events::begin()
|
||||
deepSleepObserver.observe(¬ifyDeepSleep);
|
||||
rebootObserver.observe(¬ifyReboot);
|
||||
textMessageObserver.observe(textMessageModule);
|
||||
#if !MESHTASTIC_EXCLUDE_ADMIN
|
||||
adminMessageObserver.observe(adminModule);
|
||||
#endif
|
||||
#ifdef ARCH_ESP32
|
||||
lightSleepObserver.observe(¬ifyLightSleep);
|
||||
#endif
|
||||
@@ -117,8 +122,13 @@ int InkHUD::Events::beforeReboot(void *unused)
|
||||
sa->onReboot();
|
||||
}
|
||||
|
||||
inkhud->persistence->saveSettings();
|
||||
inkhud->persistence->saveLatestMessage();
|
||||
// Save settings to flash, or erase if factory reset in progress
|
||||
if (!eraseOnReboot) {
|
||||
inkhud->persistence->saveSettings();
|
||||
inkhud->persistence->saveLatestMessage();
|
||||
} else {
|
||||
NicheGraphics::clearFlashData();
|
||||
}
|
||||
|
||||
// Note: no forceUpdate call here
|
||||
// We don't have any final screen to draw, although LogoApplet::onReboot did already display a "rebooting" screen
|
||||
@@ -171,6 +181,23 @@ int InkHUD::Events::onReceiveTextMessage(const meshtastic_MeshPacket *packet)
|
||||
return 0; // Tell caller to continue notifying other observers. (No reason to abort this event)
|
||||
}
|
||||
|
||||
int InkHUD::Events::onAdminMessage(const meshtastic_AdminMessage *message)
|
||||
{
|
||||
switch (message->which_payload_variant) {
|
||||
// Factory reset
|
||||
// Two possible messages. One preserves BLE bonds, other wipes. Both should clear InkHUD data.
|
||||
case meshtastic_AdminMessage_factory_reset_device_tag:
|
||||
case meshtastic_AdminMessage_factory_reset_config_tag:
|
||||
eraseOnReboot = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0; // Tell caller to continue notifying other observers. (No reason to abort this event)
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Callback for lightSleepObserver
|
||||
// Make sure the display is not partway through an update when we begin light sleep
|
||||
|
||||
@@ -33,6 +33,7 @@ class Events
|
||||
int beforeDeepSleep(void *unused); // Prepare for shutdown
|
||||
int beforeReboot(void *unused); // Prepare for reboot
|
||||
int onReceiveTextMessage(const meshtastic_MeshPacket *packet); // Store most recent text message
|
||||
int onAdminMessage(const meshtastic_AdminMessage *message); // Handle incoming admin messages
|
||||
#ifdef ARCH_ESP32
|
||||
int beforeLightSleep(void *unused); // Prepare for light sleep
|
||||
#endif
|
||||
@@ -52,10 +53,17 @@ class Events
|
||||
CallbackObserver<Events, const meshtastic_MeshPacket *> textMessageObserver =
|
||||
CallbackObserver<Events, const meshtastic_MeshPacket *>(this, &Events::onReceiveTextMessage);
|
||||
|
||||
// Get notified of incoming admin messages, and handle any which are relevant to InkHUD
|
||||
CallbackObserver<Events, const meshtastic_AdminMessage *> adminMessageObserver =
|
||||
CallbackObserver<Events, const meshtastic_AdminMessage *>(this, &Events::onAdminMessage);
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Get notified when the system is entering light sleep
|
||||
CallbackObserver<Events, void *> lightSleepObserver = CallbackObserver<Events, void *>(this, &Events::beforeLightSleep);
|
||||
#endif
|
||||
|
||||
// If set, InkHUD's data will be erased during onReboot
|
||||
bool eraseOnReboot = false;
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
@@ -22,6 +22,8 @@ InkHUD::MessageStore::MessageStore(std::string label)
|
||||
}
|
||||
|
||||
// Write the contents of the MessageStore::messages object to flash
|
||||
// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card.
|
||||
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally
|
||||
void InkHUD::MessageStore::saveToFlash()
|
||||
{
|
||||
assert(!filename.empty());
|
||||
@@ -29,7 +31,9 @@ void InkHUD::MessageStore::saveToFlash()
|
||||
#ifdef FSCom
|
||||
// Make the directory, if doesn't already exist
|
||||
// This is the same directory accessed by NicheGraphics::FlashData
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/NicheGraphics");
|
||||
spiLock->unlock();
|
||||
|
||||
// Open or create the file
|
||||
// No "full atomic": don't save then rename
|
||||
@@ -37,6 +41,9 @@ void InkHUD::MessageStore::saveToFlash()
|
||||
|
||||
LOG_INFO("Saving messages in %s", filename.c_str());
|
||||
|
||||
// Take firmware's SPI Lock while writing
|
||||
spiLock->lock();
|
||||
|
||||
// 1st byte: how many messages will be written to store
|
||||
f.write(messages.size());
|
||||
|
||||
@@ -51,6 +58,9 @@ void InkHUD::MessageStore::saveToFlash()
|
||||
LOG_DEBUG("Wrote message %u, length %u, text \"%s\"", (uint32_t)i, min(MAX_MESSAGE_SIZE, m.text.size()), m.text.c_str());
|
||||
}
|
||||
|
||||
// Release firmware's SPI lock, because SafeFile::close needs it
|
||||
spiLock->unlock();
|
||||
|
||||
bool writeSucceeded = f.close();
|
||||
|
||||
if (!writeSucceeded) {
|
||||
@@ -63,6 +73,7 @@ void InkHUD::MessageStore::saveToFlash()
|
||||
|
||||
// Attempt to load the previous contents of the MessageStore:message deque from flash.
|
||||
// Filename is controlled by the "label" parameter
|
||||
// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card.
|
||||
void InkHUD::MessageStore::loadFromFlash()
|
||||
{
|
||||
// Hopefully redundant. Initial intention is to only load / save once per boot.
|
||||
@@ -70,6 +81,9 @@ void InkHUD::MessageStore::loadFromFlash()
|
||||
|
||||
#ifdef FSCom
|
||||
|
||||
// Take the firmware's SPI Lock, in case filesystem is on SD card
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
|
||||
// Check that the file *does* actually exist
|
||||
if (!FSCom.exists(filename.c_str())) {
|
||||
LOG_WARN("'%s' not found. Using default values", filename.c_str());
|
||||
|
||||
@@ -502,6 +502,10 @@ Applets themselves do also listen separately for various events, but for the pur
|
||||
|
||||
Button input is sometimes handled by a system applet. `InkHUD::Events` determines whether the button should be handled by a specific system applet, or should instead trigger a default behavior
|
||||
|
||||
#### Factory Reset
|
||||
|
||||
The Events class handles the admin messages(s) which trigger factory reset. We set `Events::eraseOnReboot = true`, which causes `Events::onReboot` to erase the contents of InkHUD's data directory. We do this because some applets (e.g. ThreadedMessageApplet) save their own data to flash, so if we erased earlier, that data would get re-written during reboot.
|
||||
|
||||
---
|
||||
|
||||
### `InkHUD::Applet`
|
||||
|
||||
@@ -98,9 +98,8 @@ void TwoButton::setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup)
|
||||
assert(whichButton < 2);
|
||||
buttons[whichButton].pin = pin;
|
||||
buttons[whichButton].activeLogic = LOW; // Unimplemented
|
||||
buttons[whichButton].mode = internalPullup ? INPUT_PULLUP : INPUT;
|
||||
|
||||
pinMode(buttons[whichButton].pin, buttons[whichButton].mode);
|
||||
pinMode(buttons[whichButton].pin, internalPullup ? INPUT_PULLUP : INPUT);
|
||||
}
|
||||
|
||||
void TwoButton::setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs)
|
||||
@@ -182,7 +181,7 @@ void TwoButton::isrSecondary()
|
||||
void TwoButton::startThread()
|
||||
{
|
||||
if (!OSThread::enabled) {
|
||||
OSThread::setInterval(50);
|
||||
OSThread::setInterval(10);
|
||||
OSThread::enabled = true;
|
||||
}
|
||||
}
|
||||
@@ -299,7 +298,9 @@ int TwoButton::afterLightSleep(esp_sleep_wakeup_cause_t cause)
|
||||
// Manually trigger the button-down ISR
|
||||
// - during light sleep, our ISR is disabled
|
||||
// - if light sleep ends by button press, pretend our own ISR caught it
|
||||
if (cause == ESP_SLEEP_WAKEUP_GPIO)
|
||||
// - need to manually confirm by reading pin ourselves, to avoid occasional false positives
|
||||
// (false positive only when using internal pullup resistors?)
|
||||
if (cause == ESP_SLEEP_WAKEUP_GPIO && digitalRead(buttons[0].pin) == buttons[0].activeLogic)
|
||||
isrPrimary();
|
||||
|
||||
return 0; // Indicates success
|
||||
|
||||
@@ -35,7 +35,7 @@ class TwoButton : protected concurrency::OSThread
|
||||
static TwoButton *getInstance(); // Create or get the singleton instance
|
||||
void start(); // Start handling button input
|
||||
void stop(); // Stop handling button input (disconnect ISRs for sleep)
|
||||
void setWiring(uint8_t whichButton, uint8_t pin, bool internalPulldown = false);
|
||||
void setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup = false);
|
||||
void setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs);
|
||||
void setHandlerDown(uint8_t whichButton, Callback onDown);
|
||||
void setHandlerUp(uint8_t whichButton, Callback onUp);
|
||||
@@ -65,7 +65,6 @@ class TwoButton : protected concurrency::OSThread
|
||||
// Per-button config
|
||||
uint8_t pin = 0xFF; // 0xFF: unset
|
||||
bool activeLogic = LOW; // Active LOW by default. Currently unimplemented.
|
||||
uint8_t mode = INPUT; // Whether to use internal pull up / pull down resistors
|
||||
uint32_t debounceLength = 50; // Minimum length for shortpress, in ms
|
||||
uint32_t longpressLength = 500; // How long after button down to fire longpress, in ms
|
||||
volatile State state = State::REST; // Internal state
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
DeviceScreen *deviceScreen = nullptr;
|
||||
@@ -26,12 +27,10 @@ CallbackObserver<DeviceScreen, esp_sleep_wakeup_cause_t> endSleepObserver =
|
||||
void tft_task_handler(void *param = nullptr)
|
||||
{
|
||||
while (true) {
|
||||
if (deviceScreen) {
|
||||
spiLock->lock();
|
||||
deviceScreen->task_handler();
|
||||
spiLock->unlock();
|
||||
deviceScreen->sleep();
|
||||
}
|
||||
spiLock->lock();
|
||||
deviceScreen->task_handler();
|
||||
spiLock->unlock();
|
||||
deviceScreen->sleep();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +43,10 @@ void tftSetup(void)
|
||||
#else
|
||||
if (settingsMap[displayPanel] != no_screen) {
|
||||
DisplayDriverConfig displayConfig;
|
||||
static char *panels[] = {"NOSCREEN", "X11", "ST7789", "ST7735", "ST7735S", "ST7796",
|
||||
"ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
|
||||
static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S",
|
||||
"ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
|
||||
static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"};
|
||||
#ifdef USE_X11
|
||||
#if defined(USE_X11)
|
||||
if (settingsMap[displayPanel] == x11) {
|
||||
if (settingsMap[displayWidth] && settingsMap[displayHeight])
|
||||
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth],
|
||||
@@ -55,6 +54,14 @@ void tftSetup(void)
|
||||
else
|
||||
displayConfig.device(DisplayDriverConfig::device_t::X11);
|
||||
} else
|
||||
#elif defined(USE_FRAMEBUFFER)
|
||||
if (settingsMap[displayPanel] == fb) {
|
||||
if (settingsMap[displayWidth] && settingsMap[displayHeight])
|
||||
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)settingsMap[displayWidth],
|
||||
(uint16_t)settingsMap[displayHeight]);
|
||||
else
|
||||
displayConfig.device(DisplayDriverConfig::device_t::FB);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT)
|
||||
@@ -116,11 +123,15 @@ void tftSetup(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (deviceScreen) {
|
||||
#ifdef ARCH_ESP32
|
||||
tftSleepObserver.observe(¬ifyLightSleep);
|
||||
endSleepObserver.observe(¬ifyLightSleepEnd);
|
||||
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
|
||||
tftSleepObserver.observe(¬ifyLightSleep);
|
||||
endSleepObserver.observe(¬ifyLightSleepEnd);
|
||||
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
std::thread *tft_task = new std::thread([] { tft_task_handler(); });
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
51
src/main.cpp
51
src/main.cpp
@@ -105,7 +105,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
|
||||
#include "AmbientLightingThread.h"
|
||||
#include "PowerFSMThread.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "motion/AccelerometerThread.h"
|
||||
AccelerometerThread *accelerometerThread = nullptr;
|
||||
#endif
|
||||
@@ -115,13 +115,17 @@ AccelerometerThread *accelerometerThread = nullptr;
|
||||
AudioThread *audioThread = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef USE_PCA9557
|
||||
PCA9557 IOEXP;
|
||||
#endif
|
||||
|
||||
#if HAS_TFT
|
||||
extern void tftSetup(void);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_UDP_MULTICAST
|
||||
#include "mesh/udp/UdpMulticastThread.h"
|
||||
UdpMulticastThread *udpThread = nullptr;
|
||||
#include "mesh/udp/UdpMulticastHandler.h"
|
||||
UdpMulticastHandler *udpHandler = nullptr;
|
||||
#endif
|
||||
|
||||
#if defined(TCXO_OPTIONAL)
|
||||
@@ -133,6 +137,10 @@ void setupNicheGraphics();
|
||||
#include "nicheGraphics.h"
|
||||
#endif
|
||||
|
||||
#if defined(HW_SPI1_DEVICE) && defined(ARCH_ESP32)
|
||||
SPIClass SPI1(HSPI);
|
||||
#endif
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
volatile static const char slipstreamTZString[] = {USERPREFS_TZ_STRING};
|
||||
@@ -364,9 +372,11 @@ void setup()
|
||||
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
||||
#endif
|
||||
|
||||
#if !HAS_TFT
|
||||
meshtastic_Config_DisplayConfig_OledType screen_model =
|
||||
meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
|
||||
OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SEGGER
|
||||
auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
|
||||
@@ -595,6 +605,7 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAS_TFT
|
||||
auto screenInfo = i2cScanner->firstScreen();
|
||||
screen_found = screenInfo.type != ScanI2C::DeviceType::NONE ? screenInfo.address : ScanI2C::ADDRESS_NONE;
|
||||
|
||||
@@ -612,6 +623,7 @@ void setup()
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define UPDATE_FROM_SCANNER(FIND_FN)
|
||||
|
||||
@@ -680,7 +692,7 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#if !defined(ARCH_STM32WL)
|
||||
auto acc_info = i2cScanner->firstAccelerometer();
|
||||
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
|
||||
LOG_DEBUG("acc_info = %i", acc_info.type);
|
||||
@@ -779,9 +791,11 @@ void setup()
|
||||
else
|
||||
playStartMelody();
|
||||
|
||||
#if !HAS_TFT
|
||||
// fixed screen override?
|
||||
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
|
||||
screen_model = config.display.oled;
|
||||
#endif
|
||||
|
||||
#if defined(USE_SH1107)
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
|
||||
@@ -793,7 +807,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#if !defined(ARCH_STM32WL)
|
||||
if (acc_info.type != ScanI2C::DeviceType::NONE) {
|
||||
accelerometerThread = new AccelerometerThread(acc_info.type);
|
||||
}
|
||||
@@ -837,10 +851,16 @@ void setup()
|
||||
#elif !defined(ARCH_ESP32) // ARCH_RP2040
|
||||
SPI.begin();
|
||||
#else
|
||||
// ESP32
|
||||
// ESP32
|
||||
#if defined(HW_SPI1_DEVICE)
|
||||
SPI1.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
LOG_DEBUG("SPI1.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
SPI1.setFrequency(4000000);
|
||||
#else
|
||||
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
LOG_DEBUG("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
SPI.setFrequency(4000000);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Initialize the screen first so we can show the logo while we start up everything else.
|
||||
@@ -898,12 +918,12 @@ void setup()
|
||||
|
||||
#ifdef HAS_UDP_MULTICAST
|
||||
LOG_DEBUG("Start multicast thread");
|
||||
udpThread = new UdpMulticastThread();
|
||||
udpHandler = new UdpMulticastHandler();
|
||||
#ifdef ARCH_PORTDUINO
|
||||
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
|
||||
// onNetworkConnected there
|
||||
if (config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpThread->start();
|
||||
udpHandler->start();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -934,7 +954,7 @@ void setup()
|
||||
// Don't call screen setup until after nodedb is setup (because we need
|
||||
// the current region name)
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789)
|
||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS)
|
||||
screen->setup();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
|
||||
@@ -1280,7 +1300,12 @@ void setup()
|
||||
LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap());
|
||||
LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram());
|
||||
#endif
|
||||
#if !defined(ARCH_STM32WL)
|
||||
if (accelerometerThread)
|
||||
accelerometerThread->calibrate(30);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes)
|
||||
uint32_t shutdownAtMsec; // If not zero we will shutdown at this time (used to shutdown from python or mobile client)
|
||||
@@ -1310,7 +1335,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AUDIO_CONFIG;
|
||||
#endif
|
||||
// Option to explicitly include canned messages for edge cases, e.g. niche graphics
|
||||
#if (!HAS_SCREEN && NO_EXT_GPIO) && !MESHTASTIC_INCLUDE_CANNEDMSG
|
||||
#if (!HAS_SCREEN || NO_EXT_GPIO) || MESHTASTIC_EXCLUDE_CANNEDMESSAGES
|
||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_CANNEDMSG_CONFIG;
|
||||
#endif
|
||||
#if NO_EXT_GPIO
|
||||
@@ -1318,11 +1343,11 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
||||
#endif
|
||||
// Only edge case here is if we apply this a device with built in Accelerometer and want to detect interrupts
|
||||
// We'll have to macro guard against those targets potentially
|
||||
#if NO_EXT_GPIO
|
||||
#if NO_EXT_GPIO || MESHTASTIC_EXCLUDE_DETECTIONSENSOR
|
||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_DETECTIONSENSOR_CONFIG;
|
||||
#endif
|
||||
// If we don't have any GPIO and we don't have GPS, no purpose in having serial config
|
||||
#if NO_EXT_GPIO && NO_GPS
|
||||
// If we don't have any GPIO and we don't have GPS OR we don't want too - no purpose in having serial config
|
||||
#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL
|
||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
|
||||
#endif
|
||||
#ifndef ARCH_ESP32
|
||||
|
||||
@@ -51,14 +51,14 @@ extern AudioThread *audioThread;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_UDP_MULTICAST
|
||||
#include "mesh/udp/UdpMulticastThread.h"
|
||||
extern UdpMulticastThread *udpThread;
|
||||
#include "mesh/udp/UdpMulticastHandler.h"
|
||||
extern UdpMulticastHandler *udpHandler;
|
||||
#endif
|
||||
|
||||
// Global Screen singleton.
|
||||
extern graphics::Screen *screen;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "motion/AccelerometerThread.h"
|
||||
extern AccelerometerThread *accelerometerThread;
|
||||
#endif
|
||||
|
||||
@@ -345,7 +345,7 @@ void Channels::setChannel(const meshtastic_Channel &c)
|
||||
|
||||
bool Channels::anyMqttEnabled()
|
||||
{
|
||||
#if USERPREFS_EVENT_MODE
|
||||
#if USERPREFS_EVENT_MODE && !MESHTASTIC_EXCLUDE_MQTT
|
||||
// Don't publish messages on the public MQTT broker if we are in event mode
|
||||
if (mqtt && mqtt->isUsingDefaultServer()) {
|
||||
return false;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define ONE_MINUTE_MS 60 * 1000
|
||||
#define THIRTY_SECONDS_MS 30 * 1000
|
||||
#define FIVE_SECONDS_MS 5 * 1000
|
||||
#define TEN_SECONDS_MS 10 * 1000
|
||||
|
||||
#define min_default_telemetry_interval_secs 30 * 60
|
||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||
|
||||
@@ -247,8 +247,8 @@ template <typename T> void LR11x0Interface<T>::startReceive()
|
||||
lora.setPreambleLength(preambleLength); // Solve RX ack fail after direct message sent. Not sure why this is needed.
|
||||
|
||||
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
||||
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
|
||||
int err =
|
||||
lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
RadioLibInterface::startReceive();
|
||||
|
||||
@@ -450,7 +450,6 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
#ifdef ARCH_NRF52
|
||||
Bluefruit.begin();
|
||||
LOG_INFO("Clear bluetooth bonds!");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
@@ -584,7 +583,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh
|
||||
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
|
||||
|
||||
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR)) && \
|
||||
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \
|
||||
defined(ELECROW)) && \
|
||||
HAS_TFT
|
||||
// switch BT off by default; use TFT programming mode or hotkey to enable
|
||||
config.bluetooth.enabled = false;
|
||||
@@ -595,7 +595,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
config.bluetooth.fixed_pin = defaultBLEPin;
|
||||
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \
|
||||
defined(HX8357_CS) || defined(USE_ST7789)
|
||||
defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS)
|
||||
bool hasScreen = true;
|
||||
#ifdef HELTEC_MESH_NODE_T114
|
||||
uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET);
|
||||
@@ -689,7 +689,7 @@ void NodeDB::initConfigIntervals()
|
||||
|
||||
config.display.screen_on_secs = default_screen_on_secs;
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014)
|
||||
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) || defined(ELECROW)
|
||||
config.power.is_power_saving = true;
|
||||
config.display.screen_on_secs = 30;
|
||||
config.power.wait_bluetooth_secs = 30;
|
||||
|
||||
@@ -649,8 +649,10 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
|
||||
meshtastic_QueueStatus qs = router->getQueueStatus();
|
||||
service->sendQueueStatusToPhone(qs, 0, p.id);
|
||||
return false;
|
||||
} else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] &&
|
||||
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) {
|
||||
} else if (IS_ONE_OF(meshtastic_PortNum_POSITION_APP, meshtastic_PortNum_WAYPOINT_APP, meshtastic_PortNum_ALERT_APP) &&
|
||||
lastPortNumToRadio[p.decoded.portnum] &&
|
||||
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], TEN_SECONDS_MS)) {
|
||||
// TODO: [Issue #6700] Make this rate limit throttling scale up / down with the preset
|
||||
LOG_WARN("Rate limit portnum %d", p.decoded.portnum);
|
||||
meshtastic_QueueStatus qs = router->getQueueStatus();
|
||||
service->sendQueueStatusToPhone(qs, 0, p.id);
|
||||
|
||||
@@ -210,6 +210,14 @@ bool RadioLibInterface::canSleep()
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Allow other firmware components to ask whether we are currently sending a packet
|
||||
Initially implemented to protect T-Echo's capacitive touch button from spurious presses during tx
|
||||
*/
|
||||
bool RadioLibInterface::isSending()
|
||||
{
|
||||
return sendingPacket != NULL;
|
||||
}
|
||||
|
||||
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
||||
bool RadioLibInterface::cancelSending(NodeNum from, PacketId id)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
#define RADIOLIB_PIN_TYPE uint32_t
|
||||
|
||||
// In addition to the default Rx flags, we need the PREAMBLE_DETECTED flag to detect whether we are actively receiving
|
||||
#define MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS (RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1 << RADIOLIB_IRQ_PREAMBLE_DETECTED))
|
||||
|
||||
/**
|
||||
* We need to override the RadioLib ArduinoHal class to add mutex protection for SPI bus access
|
||||
*/
|
||||
@@ -132,6 +135,11 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
*/
|
||||
virtual bool isActivelyReceiving() = 0;
|
||||
|
||||
/** Are we are currently sending a packet?
|
||||
* This method is public, intending to expose this information to other firmware components
|
||||
*/
|
||||
virtual bool isSending();
|
||||
|
||||
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
||||
virtual bool cancelSending(NodeNum from, PacketId id) override;
|
||||
|
||||
|
||||
@@ -293,8 +293,8 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
}
|
||||
|
||||
#if HAS_UDP_MULTICAST
|
||||
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpThread->onSend(const_cast<meshtastic_MeshPacket *>(p));
|
||||
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpHandler->onSend(const_cast<meshtastic_MeshPacket *>(p));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -277,8 +277,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
|
||||
setStandby();
|
||||
|
||||
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
||||
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED);
|
||||
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS);
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
LOG_ERROR("SX126X startReceiveDutyCycleAuto %s%d", radioLibErr, err);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -260,8 +260,7 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED);
|
||||
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS);
|
||||
|
||||
if (err != RADIOLIB_ERR_NONE)
|
||||
LOG_ERROR("SX128X startReceive %s%d", radioLibErr, err);
|
||||
|
||||
@@ -43,7 +43,7 @@ template <class T, class U> class APIServerPort : public U, private concurrency:
|
||||
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
|
||||
*/
|
||||
T *openAPI = NULL;
|
||||
#if RAK_4631
|
||||
#if defined(RAK_4631) || defined(RAK11310)
|
||||
// Track wait time for RAK13800 Ethernet requests
|
||||
int32_t waitTime = 100;
|
||||
#endif
|
||||
|
||||
@@ -239,6 +239,14 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92,
|
||||
/* Reserved Fried Chicken ID for future use */
|
||||
meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN = 93,
|
||||
/* Heltec Magnetic Power Bank with Meshtastic compatible */
|
||||
meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94,
|
||||
/* Seeed Solar Node */
|
||||
meshtastic_HardwareModel_SEEED_SOLAR_NODE = 95,
|
||||
/* NomadStar Meteor Pro https://nomadstar.ch/ */
|
||||
meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO = 96,
|
||||
/* Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin */
|
||||
meshtastic_HardwareModel_CROWPANEL = 97,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
@@ -79,7 +79,10 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode {
|
||||
/* NMEA messages specifically tailored for CalTopo */
|
||||
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO = 5,
|
||||
/* Ecowitt WS85 weather station */
|
||||
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6
|
||||
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6,
|
||||
/* VE.Direct is a serial protocol used by Victron Energy products
|
||||
https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable */
|
||||
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT = 7
|
||||
} meshtastic_ModuleConfig_SerialConfig_Serial_Mode;
|
||||
|
||||
/* TODO: REPLACE */
|
||||
@@ -467,8 +470,8 @@ extern "C" {
|
||||
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
|
||||
|
||||
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT
|
||||
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85
|
||||
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85+1))
|
||||
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT
|
||||
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT+1))
|
||||
|
||||
#define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE
|
||||
#define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK
|
||||
|
||||
@@ -13,12 +13,11 @@
|
||||
#endif // HAS_ETHERNET
|
||||
|
||||
#define UDP_MULTICAST_DEFAUL_PORT 4403 // Default port for UDP multicast is same as TCP api server
|
||||
#define UDP_MULTICAST_THREAD_INTERVAL_MS 15000
|
||||
|
||||
class UdpMulticastThread : public concurrency::OSThread
|
||||
class UdpMulticastHandler final
|
||||
{
|
||||
public:
|
||||
UdpMulticastThread() : OSThread("UdpMulticast") { udpIpAddress = IPAddress(224, 0, 0, 69); }
|
||||
UdpMulticastHandler() { udpIpAddress = IPAddress(224, 0, 0, 69); }
|
||||
|
||||
void start()
|
||||
{
|
||||
@@ -71,14 +70,6 @@ class UdpMulticastThread : public concurrency::OSThread
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
canSleep = true;
|
||||
// TODO: Implement nodeinfo broadcast
|
||||
return UDP_MULTICAST_THREAD_INTERVAL_MS;
|
||||
}
|
||||
|
||||
private:
|
||||
IPAddress udpIpAddress;
|
||||
AsyncUDP udp;
|
||||
@@ -133,8 +133,8 @@ static void onNetworkConnected()
|
||||
}
|
||||
|
||||
#if HAS_UDP_MULTICAST
|
||||
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpThread->start();
|
||||
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpHandler->start();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "modules/PositionModule.h"
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "motion/AccelerometerThread.h"
|
||||
#endif
|
||||
|
||||
@@ -284,7 +284,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
case meshtastic_AdminMessage_remove_by_nodenum_tag: {
|
||||
LOG_INFO("Client received remove_nodenum command");
|
||||
nodeDB->removeNodeByNum(r->remove_by_nodenum);
|
||||
this->notifyObservers(r); // Observed by screen
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_set_favorite_node_tag: {
|
||||
@@ -444,6 +443,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
}
|
||||
|
||||
// Allow any observers (e.g. the UI) to respond to this event
|
||||
notifyObservers(r);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
28
src/modules/GenericThreadModule.cpp
Normal file
28
src/modules/GenericThreadModule.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "GenericThreadModule.h"
|
||||
#include "MeshService.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
Generic Thread Module allows for the execution of custom code at a set interval.
|
||||
*/
|
||||
GenericThreadModule *genericThreadModule;
|
||||
|
||||
GenericThreadModule::GenericThreadModule() : concurrency::OSThread("GenericThreadModule") {}
|
||||
|
||||
int32_t GenericThreadModule::runOnce()
|
||||
{
|
||||
|
||||
bool enabled = true;
|
||||
if (!enabled)
|
||||
return disable();
|
||||
|
||||
if (firstTime) {
|
||||
// do something the first time we run
|
||||
firstTime = 0;
|
||||
LOG_INFO("first time GenericThread running");
|
||||
}
|
||||
|
||||
LOG_INFO("GenericThread executing");
|
||||
return (my_interval);
|
||||
}
|
||||
21
src/modules/GenericThreadModule.h
Normal file
21
src/modules/GenericThreadModule.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "MeshModule.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
class GenericThreadModule : private concurrency::OSThread
|
||||
{
|
||||
bool firstTime = 1;
|
||||
|
||||
public:
|
||||
GenericThreadModule();
|
||||
|
||||
protected:
|
||||
unsigned int my_interval = 10000; // interval in millisconds
|
||||
virtual int32_t runOnce() override;
|
||||
};
|
||||
|
||||
extern GenericThreadModule *genericThreadModule;
|
||||
@@ -65,6 +65,10 @@
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY
|
||||
#include "modules/Telemetry/PowerTelemetry.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
||||
#include "modules/GenericThreadModule.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if defined(USE_SX1280) && !MESHTASTIC_EXCLUDE_AUDIO
|
||||
#include "modules/esp32/AudioModule.h"
|
||||
@@ -131,6 +135,9 @@ void setupModules()
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
dropzoneModule = new DropzoneModule();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
||||
new GenericThreadModule();
|
||||
#endif
|
||||
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
||||
// to a global variable.
|
||||
@@ -249,4 +256,4 @@ void setupModules()
|
||||
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
|
||||
// acks
|
||||
routingModule = new RoutingModule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,9 +370,16 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
|
||||
if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER,
|
||||
meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) &&
|
||||
config.power.is_power_saving) {
|
||||
LOG_DEBUG("Start next execution in 5s, then sleep");
|
||||
meshtastic_ClientNotification *notification = clientNotificationPool.allocZeroed();
|
||||
notification->level = meshtastic_LogRecord_Level_INFO;
|
||||
notification->time = getValidTime(RTCQualityFromNet);
|
||||
sprintf(notification->message, "Sending position and sleeping for %us interval in a moment",
|
||||
Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs) /
|
||||
1000U);
|
||||
service->sendClientNotification(notification);
|
||||
sleepOnNextExecution = true;
|
||||
setIntervalFromNow(5000);
|
||||
LOG_DEBUG("Start next execution in 5s, then sleep");
|
||||
setIntervalFromNow(FIVE_SECONDS_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -513,7 +513,7 @@ void SerialModule::processWXSerial()
|
||||
// Extract the current line
|
||||
char line[meshtastic_Constants_DATA_PAYLOAD_LEN];
|
||||
memset(line, '\0', sizeof(line));
|
||||
if (lineEnd - lineStart < sizeof(line) - 1) {
|
||||
if ((size_t)(lineEnd - lineStart) < sizeof(line) - 1) {
|
||||
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
|
||||
|
||||
ParsedLine parsed = parseLine(line);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("Adafruit_PM25AQI.h")
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "AirQualityTelemetry.h"
|
||||
@@ -14,6 +14,13 @@
|
||||
#include "main.h"
|
||||
#include <Throttle.h>
|
||||
|
||||
#ifndef PMSA003I_WARMUP_MS
|
||||
// from the PMSA003I datasheet:
|
||||
// "Stable data should be got at least 30 seconds after the sensor wakeup
|
||||
// from the sleep mode because of the fan’s performance."
|
||||
#define PMSA003I_WARMUP_MS 30000
|
||||
#endif
|
||||
|
||||
int32_t AirQualityTelemetryModule::runOnce()
|
||||
{
|
||||
/*
|
||||
@@ -34,6 +41,13 @@ int32_t AirQualityTelemetryModule::runOnce()
|
||||
|
||||
if (moduleConfig.telemetry.air_quality_enabled) {
|
||||
LOG_INFO("Air quality Telemetry: init");
|
||||
|
||||
#ifdef PMSA003I_ENABLE_PIN
|
||||
// put the sensor to sleep on startup
|
||||
pinMode(PMSA003I_ENABLE_PIN, OUTPUT);
|
||||
digitalWrite(PMSA003I_ENABLE_PIN, LOW);
|
||||
#endif /* PMSA003I_ENABLE_PIN */
|
||||
|
||||
if (!aqi.begin_I2C()) {
|
||||
#ifndef I2C_NO_RESCAN
|
||||
LOG_WARN("Could not establish i2c connection to AQI sensor. Rescan");
|
||||
@@ -63,21 +77,45 @@ int32_t AirQualityTelemetryModule::runOnce()
|
||||
if (!moduleConfig.telemetry.air_quality_enabled)
|
||||
return disable();
|
||||
|
||||
if (((lastSentToMesh == 0) ||
|
||||
!Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled(
|
||||
moduleConfig.telemetry.air_quality_interval,
|
||||
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
|
||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = millis();
|
||||
} else if (service->isToPhoneQueueEmpty()) {
|
||||
// Just send to phone when it's not our time to send to mesh yet
|
||||
// Only send while queue is empty (phone assumed connected)
|
||||
sendTelemetry(NODENUM_BROADCAST, true);
|
||||
switch (state) {
|
||||
#ifdef PMSA003I_ENABLE_PIN
|
||||
case State::IDLE:
|
||||
// sensor is in standby; fire it up and sleep
|
||||
LOG_DEBUG("runOnce(): state = idle");
|
||||
digitalWrite(PMSA003I_ENABLE_PIN, HIGH);
|
||||
state = State::ACTIVE;
|
||||
|
||||
return PMSA003I_WARMUP_MS;
|
||||
#endif /* PMSA003I_ENABLE_PIN */
|
||||
case State::ACTIVE:
|
||||
// sensor is already warmed up; grab telemetry and send it
|
||||
LOG_DEBUG("runOnce(): state = active");
|
||||
|
||||
if (((lastSentToMesh == 0) ||
|
||||
!Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled(
|
||||
moduleConfig.telemetry.air_quality_interval,
|
||||
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
|
||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = millis();
|
||||
} else if (service->isToPhoneQueueEmpty()) {
|
||||
// Just send to phone when it's not our time to send to mesh yet
|
||||
// Only send while queue is empty (phone assumed connected)
|
||||
sendTelemetry(NODENUM_BROADCAST, true);
|
||||
}
|
||||
|
||||
#ifdef PMSA003I_ENABLE_PIN
|
||||
// put sensor back to sleep
|
||||
digitalWrite(PMSA003I_ENABLE_PIN, LOW);
|
||||
state = State::IDLE;
|
||||
#endif /* PMSA003I_ENABLE_PIN */
|
||||
|
||||
return sendToPhoneIntervalMs;
|
||||
default:
|
||||
return disable();
|
||||
}
|
||||
}
|
||||
return sendToPhoneIntervalMs;
|
||||
}
|
||||
|
||||
bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("Adafruit_PM25AQI.h")
|
||||
|
||||
#pragma once
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
@@ -23,6 +23,14 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf
|
||||
setIntervalFromNow(10 * 1000);
|
||||
aqi = Adafruit_PM25AQI();
|
||||
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
||||
|
||||
#ifdef PMSA003I_ENABLE_PIN
|
||||
// the PMSA003I sensor uses about 300mW on its own; support powering it off when it's not actively taking
|
||||
// a reading
|
||||
state = State::IDLE;
|
||||
#else
|
||||
state = State::ACTIVE;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -42,6 +50,12 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf
|
||||
bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
||||
|
||||
private:
|
||||
enum State {
|
||||
IDLE = 0,
|
||||
ACTIVE = 1,
|
||||
};
|
||||
|
||||
State state;
|
||||
Adafruit_PM25AQI aqi;
|
||||
PM25_AQI_Data data = {0};
|
||||
bool firstTime = true;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user