Merge branch 'develop' into clear-rangetest-results
This commit is contained in:
@@ -76,7 +76,7 @@ bool loopCanSleep()
|
|||||||
// Called just prior to starting Meshtastic. Allows for setting config values before startup.
|
// Called just prior to starting Meshtastic. Allows for setting config values before startup.
|
||||||
void lateInitVariant()
|
void lateInitVariant()
|
||||||
{
|
{
|
||||||
settingsMap[logoutputlevel] = level_error;
|
portduino_config.logoutputlevel = level_error;
|
||||||
channelFile.channels[0] = meshtastic_Channel{
|
channelFile.channels[0] = meshtastic_Channel{
|
||||||
.has_settings = true,
|
.has_settings = true,
|
||||||
.settings =
|
.settings =
|
||||||
@@ -132,7 +132,7 @@ int portduino_main(int argc, char **argv); // Renamed "main" function from Mesht
|
|||||||
// Start Meshtastic in a thread and wait till it has reached the ON state.
|
// Start Meshtastic in a thread and wait till it has reached the ON state.
|
||||||
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||||
{
|
{
|
||||||
settingsMap[maxtophone] = 5;
|
portduino_config.maxtophone = 5;
|
||||||
|
|
||||||
meshtasticThread = std::thread([program = *argv[0]]() {
|
meshtasticThread = std::thread([program = *argv[0]]() {
|
||||||
char nodeIdStr[12];
|
char nodeIdStr[12];
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ runs:
|
|||||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
|
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|||||||
@@ -43,11 +43,15 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
cache: pip
|
cache: pip
|
||||||
- run: pip install -U platformio
|
- run: pip install -U platformio
|
||||||
|
- name: Uncomment build epoch
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||||
- name: Generate matrix
|
- name: Generate matrix
|
||||||
id: jsonStep
|
id: jsonStep
|
||||||
run: |
|
run: |
|
||||||
@@ -370,7 +374,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
@@ -439,7 +443,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
@@ -494,7 +498,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Check for PR labels
|
- name: Check for PR labels
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v8
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const labels = context.payload.pull_request.labels.map(label => label.name);
|
const labels = context.payload.pull_request.labels.map(label => label.name);
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Comment test results on PR
|
- name: Comment test results on PR
|
||||||
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v8
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Stale PR+Issues
|
- name: Stale PR+Issues
|
||||||
uses: actions/stale@v9.1.0
|
uses: actions/stale@v10.0.0
|
||||||
with:
|
with:
|
||||||
days-before-stale: 45
|
days-before-stale: 45
|
||||||
exempt-issue-labels: pinned,3.0
|
exempt-issue-labels: pinned,3.0
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
pio upgrade
|
pio upgrade
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v5
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 22
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
git push
|
git push
|
||||||
|
|
||||||
- name: Comment on PR
|
- name: Comment on PR
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v8
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
|
|||||||
+4
-4
@@ -8,13 +8,13 @@ plugins:
|
|||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.467
|
- checkov@3.2.469
|
||||||
- renovate@41.90.1
|
- renovate@41.94.0
|
||||||
- prettier@3.6.2
|
- prettier@3.6.2
|
||||||
- trufflehog@3.90.5
|
- trufflehog@3.90.5
|
||||||
- yamllint@1.37.1
|
- yamllint@1.37.1
|
||||||
- bandit@1.8.6
|
- bandit@1.8.6
|
||||||
- trivy@0.65.0
|
- trivy@0.66.0
|
||||||
- taplo@0.10.0
|
- taplo@0.10.0
|
||||||
- ruff@0.12.11
|
- ruff@0.12.11
|
||||||
- isort@6.0.1
|
- isort@6.0.1
|
||||||
@@ -23,7 +23,7 @@ lint:
|
|||||||
- svgo@4.0.0
|
- svgo@4.0.0
|
||||||
- actionlint@1.7.7
|
- actionlint@1.7.7
|
||||||
- flake8@7.3.0
|
- flake8@7.3.0
|
||||||
- hadolint@2.12.1-beta
|
- hadolint@2.13.1
|
||||||
- shfmt@3.6.0
|
- shfmt@3.6.0
|
||||||
- shellcheck@0.11.0
|
- shellcheck@0.11.0
|
||||||
- black@25.1.0
|
- black@25.1.0
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
[portduino_base]
|
[portduino_base]
|
||||||
platform =
|
platform =
|
||||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||||
https://github.com/meshtastic/platform-native/archive/37d986499ce24511952d7146db72d667c6bdaff7.zip
|
https://github.com/meshtastic/platform-native/archive/c490bcd019e0658404088a61b96e653c9da22c45.zip
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
@@ -31,6 +31,8 @@ lib_deps =
|
|||||||
https://github.com/pine64/libch341-spi-userspace/archive/af9bc27c9c30fa90772279925b7c5913dff789b4.zip
|
https://github.com/pine64/libch341-spi-userspace/archive/af9bc27c9c30fa90772279925b7c5913dff789b4.zip
|
||||||
# renovate: datasource=custom.pio depName=adafruit/Adafruit seesaw Library packageName=adafruit/library/Adafruit seesaw Library
|
# renovate: datasource=custom.pio depName=adafruit/Adafruit seesaw Library packageName=adafruit/library/Adafruit seesaw Library
|
||||||
adafruit/Adafruit seesaw Library@1.7.9
|
adafruit/Adafruit seesaw Library@1.7.9
|
||||||
|
# renovate: datasource=git-refs depName=RAK12034-BMX160 packageName=https://github.com/RAKWireless/RAK12034-BMX160 gitBranch=main
|
||||||
|
https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
|
|||||||
+23
-6
@@ -7,6 +7,7 @@ SET "DEBUG=0"
|
|||||||
SET "PYTHON="
|
SET "PYTHON="
|
||||||
SET "TFT_BUILD=0"
|
SET "TFT_BUILD=0"
|
||||||
SET "BIGDB8=0"
|
SET "BIGDB8=0"
|
||||||
|
SET "MUIDB8=0"
|
||||||
SET "BIGDB16=0"
|
SET "BIGDB16=0"
|
||||||
SET "ESPTOOL_BAUD=115200"
|
SET "ESPTOOL_BAUD=115200"
|
||||||
SET "ESPTOOL_CMD="
|
SET "ESPTOOL_CMD="
|
||||||
@@ -14,11 +15,12 @@ SET "LOGCOUNTER=0"
|
|||||||
SET "BPS_RESET=0"
|
SET "BPS_RESET=0"
|
||||||
|
|
||||||
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable.
|
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable.
|
||||||
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
|
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone t-eth-elite tlora-pager mesh-tab dreamcatcher ESP32-S3-Pico seeed-sensecap-indicator heltec_capsule_sensor_v3 vision-master icarus tracksenger elecrow-adv"
|
||||||
SET "C3=esp32c3"
|
SET "C3=esp32c3"
|
||||||
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
|
@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 tracksenger"
|
SET "BIGDB_8MB=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"
|
SET "MUIDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator"
|
||||||
|
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite tlora-pager t-watch-s3 elecrow-adv"
|
||||||
|
|
||||||
GOTO getopts
|
GOTO getopts
|
||||||
:help
|
:help
|
||||||
@@ -119,11 +121,10 @@ IF NOT "__%PYTHON%__"=="____" (
|
|||||||
|
|
||||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||||
!ESPTOOL_CMD! >nul 2>&1
|
!ESPTOOL_CMD! >nul 2>&1
|
||||||
IF %ERRORLEVEL% GEQ 2 (
|
IF %ERRORLEVEL% EQU 9009 (
|
||||||
@REM esptool exits with code 1 if help is displayed.
|
@REM 9009 = command not found on Windows
|
||||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||||
EXIT /B 1
|
EXIT /B 1
|
||||||
GOTO eof
|
|
||||||
)
|
)
|
||||||
IF %DEBUG% EQU 1 (
|
IF %DEBUG% EQU 1 (
|
||||||
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
||||||
@@ -163,6 +164,15 @@ FOR %%a IN (%BIGDB_8MB%) DO (
|
|||||||
)
|
)
|
||||||
:end_loop_bigdb_8mb
|
:end_loop_bigdb_8mb
|
||||||
|
|
||||||
|
FOR %%a IN (%MUIDB_8MB%) DO (
|
||||||
|
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||||
|
@REM We are working with any of %MUIDB_8MB%.
|
||||||
|
SET "MUIDB8=1"
|
||||||
|
GOTO end_loop_muidb_8mb
|
||||||
|
)
|
||||||
|
)
|
||||||
|
:end_loop_muidb_8mb
|
||||||
|
|
||||||
FOR %%a IN (%BIGDB_16MB%) DO (
|
FOR %%a IN (%BIGDB_16MB%) DO (
|
||||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||||
@REM We are working with any of %BIGDB_16MB%.
|
@REM We are working with any of %BIGDB_16MB%.
|
||||||
@@ -173,6 +183,7 @@ FOR %%a IN (%BIGDB_16MB%) DO (
|
|||||||
:end_loop_bigdb_16mb
|
:end_loop_bigdb_16mb
|
||||||
|
|
||||||
IF %BIGDB8% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 8mb partition selected."
|
IF %BIGDB8% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 8mb partition selected."
|
||||||
|
IF %MUIDB8% EQU 1 CALL :LOG_MESSAGE INFO "MUIDB 8mb partition selected."
|
||||||
IF %BIGDB16% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 16mb partition selected."
|
IF %BIGDB16% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 16mb partition selected."
|
||||||
|
|
||||||
@REM Extract BASENAME from %FILENAME% for later use.
|
@REM Extract BASENAME from %FILENAME% for later use.
|
||||||
@@ -217,6 +228,12 @@ IF %BIGDB8% EQU 1 (
|
|||||||
SET "SPIFFS_OFFSET=0x670000"
|
SET "SPIFFS_OFFSET=0x670000"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@REM Offsets for MUIDB 8mb.
|
||||||
|
IF %MUIDB8% EQU 1 (
|
||||||
|
SET "OTA_OFFSET=0x5D0000"
|
||||||
|
SET "SPIFFS_OFFSET=0x670000"
|
||||||
|
)
|
||||||
|
|
||||||
@REM Offsets for BigDB 16mb.
|
@REM Offsets for BigDB 16mb.
|
||||||
IF %BIGDB16% EQU 1 (
|
IF %BIGDB16% EQU 1 (
|
||||||
SET "OTA_OFFSET=0x650000"
|
SET "OTA_OFFSET=0x650000"
|
||||||
|
|||||||
+44
-31
@@ -5,38 +5,43 @@ BPS_RESET=false
|
|||||||
TFT_BUILD=false
|
TFT_BUILD=false
|
||||||
MCU=""
|
MCU=""
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
RESET_BAUD=1200
|
||||||
|
FIRMWARE_OFFSET=0x00
|
||||||
|
|
||||||
# Variant groups
|
# Variant groups
|
||||||
BIGDB_8MB=(
|
BIGDB_8MB=(
|
||||||
"picomputer-s3"
|
"crowpanel-esp32s3"
|
||||||
"unphone"
|
"heltec_capsule_sensor_v3"
|
||||||
"seeed-sensecap-indicator"
|
"heltec-v3"
|
||||||
"crowpanel-esp32s3"
|
"heltec-vision-master-e213"
|
||||||
"heltec_capsule_sensor_v3"
|
"heltec-vision-master-e290"
|
||||||
"heltec-v3"
|
"heltec-vision-master-t190"
|
||||||
"heltec-vision-master-e213"
|
"heltec-wireless-paper"
|
||||||
"heltec-vision-master-e290"
|
"heltec-wireless-tracker"
|
||||||
"heltec-vision-master-t190"
|
"heltec-wsl-v3"
|
||||||
"heltec-wireless-paper"
|
"icarus"
|
||||||
"heltec-wireless-tracker"
|
"seeed-xiao-s3"
|
||||||
"heltec-wsl-v3"
|
"tbeam-s3-core"
|
||||||
"icarus"
|
"tracksenger"
|
||||||
"seeed-xiao-s3"
|
)
|
||||||
"tbeam-s3-core"
|
MUIDB_8MB=(
|
||||||
"tracksenger"
|
"picomputer-s3"
|
||||||
|
"unphone"
|
||||||
|
"seeed-sensecap-indicator"
|
||||||
)
|
)
|
||||||
BIGDB_16MB=(
|
BIGDB_16MB=(
|
||||||
"t-deck"
|
"t-deck"
|
||||||
"mesh-tab"
|
"mesh-tab"
|
||||||
"t-energy-s3"
|
"t-energy-s3"
|
||||||
"dreamcatcher"
|
"dreamcatcher"
|
||||||
"ESP32-S3-Pico"
|
"ESP32-S3-Pico"
|
||||||
"m5stack-cores3"
|
"m5stack-cores3"
|
||||||
"station-g2"
|
"station-g2"
|
||||||
"t-eth-elite"
|
"t-eth-elite"
|
||||||
|
"tlora-pager"
|
||||||
"t-watch-s3"
|
"t-watch-s3"
|
||||||
"elecrow-adv-35-tft"
|
"elecrow-adv"
|
||||||
"elecrow-adv-24-28-tft"
|
|
||||||
"elecrow-adv1-43-50-70-tft"
|
|
||||||
)
|
)
|
||||||
S3_VARIANTS=(
|
S3_VARIANTS=(
|
||||||
"s3"
|
"s3"
|
||||||
@@ -47,6 +52,7 @@ S3_VARIANTS=(
|
|||||||
"station-g2"
|
"station-g2"
|
||||||
"unphone"
|
"unphone"
|
||||||
"t-eth-elite"
|
"t-eth-elite"
|
||||||
|
"tlora-pager"
|
||||||
"mesh-tab"
|
"mesh-tab"
|
||||||
"dreamcatcher"
|
"dreamcatcher"
|
||||||
"ESP32-S3-Pico"
|
"ESP32-S3-Pico"
|
||||||
@@ -106,8 +112,8 @@ while [ $# -gt 0 ]; do
|
|||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--1200bps-reset)
|
--1200bps-reset)
|
||||||
BPS_RESET=true
|
BPS_RESET=true
|
||||||
;;
|
;;
|
||||||
--) # Stop parsing options
|
--) # Stop parsing options
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
@@ -121,7 +127,7 @@ while [ $# -gt 0 ]; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ $BPS_RESET == true ]]; then
|
if [[ $BPS_RESET == true ]]; then
|
||||||
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
|
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -158,6 +164,13 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
for variant in "${MUIDB_8MB[@]}"; do
|
||||||
|
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||||
|
OFFSET=0x670000
|
||||||
|
OTA_OFFSET=0x5D0000
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# littlefs* offset for BigDB 16mb and OTA OFFSET.
|
# littlefs* offset for BigDB 16mb and OTA OFFSET.
|
||||||
for variant in "${BIGDB_16MB[@]}"; do
|
for variant in "${BIGDB_16MB[@]}"; do
|
||||||
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
if [ -z "${FILENAME##*"$variant"*}" ]; then
|
||||||
@@ -201,8 +214,8 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||||
$ESPTOOL_CMD erase_flash
|
$ESPTOOL_CMD erase-flash
|
||||||
$ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
|
$ESPTOOL_CMD write-flash $FIRMWARE_OFFSET "${FILENAME}"
|
||||||
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
|
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
|
||||||
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
|
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
|
||||||
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
|
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
|
||||||
|
|||||||
+12
-11
@@ -6,6 +6,8 @@ SET "SCRIPT_NAME=%~nx0"
|
|||||||
SET "DEBUG=0"
|
SET "DEBUG=0"
|
||||||
SET "PYTHON="
|
SET "PYTHON="
|
||||||
SET "ESPTOOL_BAUD=115200"
|
SET "ESPTOOL_BAUD=115200"
|
||||||
|
SET "RESET_BAUD=1200"
|
||||||
|
SET "UPDATE_OFFSET=0x10000"
|
||||||
SET "ESPTOOL_CMD="
|
SET "ESPTOOL_CMD="
|
||||||
SET "LOGCOUNTER=0"
|
SET "LOGCOUNTER=0"
|
||||||
SET "CHANGE_MODE=0"
|
SET "CHANGE_MODE=0"
|
||||||
@@ -85,14 +87,13 @@ IF "!FILENAME:update=!"=="!FILENAME!" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
:skip-filename
|
:skip-filename
|
||||||
SET "ESPTOOL_BAUD=1200"
|
|
||||||
|
|
||||||
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
|
||||||
IF NOT "__%PYTHON%__"=="____" (
|
IF NOT "__%PYTHON%__"=="____" (
|
||||||
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
|
SET "ESPTOOL_CMD=""!PYTHON!"" -m esptool"
|
||||||
CALL :LOG_MESSAGE DEBUG "Python interpreter supplied."
|
CALL :LOG_MESSAGE DEBUG "Python interpreter supplied."
|
||||||
) ELSE (
|
) ELSE (
|
||||||
CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool...
|
CALL :LOG_MESSAGE DEBUG "Python interpreter NOT supplied. Looking for esptool..."
|
||||||
WHERE esptool >nul 2>&1
|
WHERE esptool >nul 2>&1
|
||||||
IF %ERRORLEVEL% EQU 0 (
|
IF %ERRORLEVEL% EQU 0 (
|
||||||
@REM WHERE exits with code 0 if esptool is found.
|
@REM WHERE exits with code 0 if esptool is found.
|
||||||
@@ -105,11 +106,11 @@ IF NOT "__%PYTHON%__"=="____" (
|
|||||||
|
|
||||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||||
!ESPTOOL_CMD! >nul 2>&1
|
!ESPTOOL_CMD! >nul 2>&1
|
||||||
IF %ERRORLEVEL% GEQ 2 (
|
CALL :LOG_MESSAGE DEBUG "esptool exit code: %ERRORLEVEL%"
|
||||||
@REM esptool exits with code 1 if help is displayed.
|
IF %ERRORLEVEL% EQU 9009 (
|
||||||
|
@REM 9009 = command not found on Windows
|
||||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||||
EXIT /B 1
|
EXIT /B 1
|
||||||
GOTO eof
|
|
||||||
)
|
)
|
||||||
IF %DEBUG% EQU 1 (
|
IF %DEBUG% EQU 1 (
|
||||||
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
CALL :LOG_MESSAGE DEBUG "Skipping ESPTOOL_CMD steps."
|
||||||
@@ -127,13 +128,13 @@ CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
|||||||
|
|
||||||
IF %CHANGE_MODE% EQU 1 (
|
IF %CHANGE_MODE% EQU 1 (
|
||||||
@REM Attempt to change mode via 1200bps Reset.
|
@REM Attempt to change mode via 1200bps Reset.
|
||||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status
|
CALL :RUN_ESPTOOL !RESET_BAUD! --after no_reset read_flash_status
|
||||||
GOTO eof
|
GOTO eof
|
||||||
)
|
)
|
||||||
|
|
||||||
@REM Flashing operations.
|
@REM Flashing operations.
|
||||||
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET 0x10000..."
|
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET !UPDATE_OFFSET!..."
|
||||||
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash 0x10000 "!FILENAME!" || GOTO eof
|
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write-flash !UPDATE_OFFSET! "!FILENAME!" || GOTO eof
|
||||||
|
|
||||||
CALL :LOG_MESSAGE INFO "Script complete!."
|
CALL :LOG_MESSAGE INFO "Script complete!."
|
||||||
|
|
||||||
@@ -145,9 +146,9 @@ EXIT /B %ERRORLEVEL%
|
|||||||
:RUN_ESPTOOL
|
:RUN_ESPTOOL
|
||||||
@REM Subroutine used to run ESPTOOL_CMD with arguments.
|
@REM Subroutine used to run ESPTOOL_CMD with arguments.
|
||||||
@REM Also handles %ERRORLEVEL%.
|
@REM Also handles %ERRORLEVEL%.
|
||||||
@REM CALL :RUN_ESPTOOL [Baud] [erase_flash|write_flash] [OFFSET] [Filename]
|
@REM CALL :RUN_ESPTOOL [Baud] [erase-flash|write-flash] [OFFSET] [Filename]
|
||||||
@REM.
|
@REM.
|
||||||
@REM Example:: CALL :RUN_ESPTOOL 115200 write_flash 0x10000 "firmwarefile.bin"
|
@REM Example:: CALL :RUN_ESPTOOL 115200 write-flash 0x10000 "firmwarefile.bin"
|
||||||
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
|
||||||
CALL :RESET_ERROR
|
CALL :RESET_ERROR
|
||||||
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
|
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
||||||
CHANGE_MODE=false
|
CHANGE_MODE=false
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
FLASH_BAUD=115200
|
||||||
|
RESET_BAUD=1200
|
||||||
|
UPDATE_OFFSET=0x10000
|
||||||
|
|
||||||
# Determine the correct esptool command to use
|
# Determine the correct esptool command to use
|
||||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||||
ESPTOOL_CMD="$PYTHON -m esptool"
|
ESPTOOL_CMD="$PYTHON -m esptool"
|
||||||
@@ -64,7 +69,7 @@ done
|
|||||||
shift "$((OPTIND-1))"
|
shift "$((OPTIND-1))"
|
||||||
|
|
||||||
if [ "$CHANGE_MODE" = true ]; then
|
if [ "$CHANGE_MODE" = true ]; then
|
||||||
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
|
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -75,7 +80,7 @@ fi
|
|||||||
|
|
||||||
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
||||||
echo "Trying to flash update ${FILENAME}"
|
echo "Trying to flash update ${FILENAME}"
|
||||||
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 "${FILENAME}"
|
$ESPTOOL_CMD --baud $FLASH_BAUD write-flash $UPDATE_OFFSET "${FILENAME}"
|
||||||
else
|
else
|
||||||
show_help
|
show_help
|
||||||
echo "Invalid file: ${FILENAME}"
|
echo "Invalid file: ${FILENAME}"
|
||||||
|
|||||||
@@ -87,6 +87,9 @@
|
|||||||
</screenshots>
|
</screenshots>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.7.9" date="2025-09-03">
|
||||||
|
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.9</url>
|
||||||
|
</release>
|
||||||
<release version="2.7.8" date="2025-08-30">
|
<release version="2.7.8" date="2025-08-30">
|
||||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.8</url>
|
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.8</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"build": {
|
"build": {
|
||||||
"arduino": {
|
"arduino": {
|
||||||
"ldscript": "esp32s3_out.ld",
|
"ldscript": "esp32s3_out.ld",
|
||||||
"partitions": "default_8MB.csv",
|
"partitions": "partition-table-8MB.csv",
|
||||||
"memory_type": "qio_opi"
|
"memory_type": "qio_opi"
|
||||||
},
|
},
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
"arduino": {
|
"arduino": {
|
||||||
"ldscript": "esp32s3_out.ld",
|
"ldscript": "esp32s3_out.ld",
|
||||||
"memory_type": "qio_opi",
|
"memory_type": "qio_opi",
|
||||||
"partitions": "default_8MB.csv"
|
"partitions": "partition-table-8MB.csv"
|
||||||
},
|
},
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": [
|
"extra_flags": [
|
||||||
|
|||||||
Vendored
+5
-2
@@ -1,4 +1,4 @@
|
|||||||
meshtasticd (2.7.8.0) UNRELEASED; urgency=medium
|
meshtasticd (2.7.9.0) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
[ Austin Lane ]
|
[ Austin Lane ]
|
||||||
* Initial packaging
|
* Initial packaging
|
||||||
@@ -44,4 +44,7 @@ meshtasticd (2.7.8.0) UNRELEASED; urgency=medium
|
|||||||
[ ]
|
[ ]
|
||||||
* GitHub Actions Automatic version bump
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
-- <github-actions[bot]@users.noreply.github.com> Sat, 30 Aug 2025 00:26:04 +0000
|
[ ]
|
||||||
|
* GitHub Actions Automatic version bump
|
||||||
|
|
||||||
|
-- <github-actions[bot]@users.noreply.github.com> Wed, 03 Sep 2025 23:39:17 +0000
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# This is a layout for 8MB of flash for MUI devices
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
|
app0, app, ota_0, 0x10000, 0x5C0000,
|
||||||
|
flashApp, app, ota_1, 0x5D0000,0x0A0000,
|
||||||
|
spiffs, data, spiffs, 0x670000,0x180000
|
||||||
|
+5
-3
@@ -118,7 +118,7 @@ lib_deps =
|
|||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||||
https://github.com/meshtastic/device-ui/archive/a3e0e1be372d069f47b4c19d718f5267251744d7.zip
|
https://github.com/meshtastic/device-ui/archive/233d18ef42e9d189f90fdfe621f0cd7edff2d221.zip
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
@@ -157,8 +157,8 @@ lib_deps =
|
|||||||
emotibit/EmotiBit MLX90632@1.0.8
|
emotibit/EmotiBit MLX90632@1.0.8
|
||||||
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
|
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
|
||||||
adafruit/Adafruit MLX90614 Library@2.1.5
|
adafruit/Adafruit MLX90614 Library@2.1.5
|
||||||
# renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221
|
# renovate: datasource=github-tags depName=INA3221 packageName=sgtwilko/INA3221
|
||||||
https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip
|
https://github.com/sgtwilko/INA3221#bb03d7e9bfcc74fc798838a54f4f99738f29fc6a
|
||||||
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
|
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
|
||||||
mprograms/QMC5883LCompass@1.2.3
|
mprograms/QMC5883LCompass@1.2.3
|
||||||
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
|
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
|
||||||
@@ -177,6 +177,8 @@ lib_deps =
|
|||||||
adafruit/Adafruit PCT2075@1.0.5
|
adafruit/Adafruit PCT2075@1.0.5
|
||||||
# renovate: datasource=custom.pio depName=DFRobot_BMM150 packageName=dfrobot/library/DFRobot_BMM150
|
# renovate: datasource=custom.pio depName=DFRobot_BMM150 packageName=dfrobot/library/DFRobot_BMM150
|
||||||
dfrobot/DFRobot_BMM150@1.0.0
|
dfrobot/DFRobot_BMM150@1.0.0
|
||||||
|
# renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561
|
||||||
|
adafruit/Adafruit TSL2561@1.1.2
|
||||||
|
|
||||||
; (not included in native / portduino)
|
; (not included in native / portduino)
|
||||||
[environmental_extra]
|
[environmental_extra]
|
||||||
|
|||||||
+1
-1
Submodule protobufs updated: 4c4427c4a7...a84657c220
@@ -146,7 +146,7 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
|
|||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
bool utf = !settingsMap[ascii_logs];
|
bool utf = !portduino_config.ascii_logs;
|
||||||
#else
|
#else
|
||||||
bool utf = true;
|
bool utf = true;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -39,3 +39,45 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *DisplayFormatters::getDeviceRole(meshtastic_Config_DeviceConfig_Role role)
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_CLIENT:
|
||||||
|
return "Client";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE:
|
||||||
|
return "Client Mute";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN:
|
||||||
|
return "Client Hidden";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND:
|
||||||
|
return "Lost and Found";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_TRACKER:
|
||||||
|
return "Tracker";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_SENSOR:
|
||||||
|
return "Sensor";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_TAK:
|
||||||
|
return "TAK";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_TAK_TRACKER:
|
||||||
|
return "TAK Tracker";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_ROUTER:
|
||||||
|
return "Router";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_ROUTER_LATE:
|
||||||
|
return "Router Late";
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DeviceConfig_Role_REPEATER:
|
||||||
|
return "Repeater";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,4 +6,7 @@ class DisplayFormatters
|
|||||||
public:
|
public:
|
||||||
static const char *getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName,
|
static const char *getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName,
|
||||||
bool usePreset);
|
bool usePreset);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const char *getDeviceRole(meshtastic_Config_DeviceConfig_Role role);
|
||||||
};
|
};
|
||||||
@@ -22,6 +22,9 @@ class GPSStatus : public Status
|
|||||||
|
|
||||||
meshtastic_Position p = meshtastic_Position_init_default;
|
meshtastic_Position p = meshtastic_Position_init_default;
|
||||||
|
|
||||||
|
/// Time of last valid GPS fix (millis since boot)
|
||||||
|
uint32_t lastFixMillis = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GPSStatus() { statusType = STATUS_TYPE_GPS; }
|
GPSStatus() { statusType = STATUS_TYPE_GPS; }
|
||||||
|
|
||||||
@@ -83,6 +86,9 @@ class GPSStatus : public Status
|
|||||||
|
|
||||||
uint32_t getNumSatellites() const { return p.sats_in_view; }
|
uint32_t getNumSatellites() const { return p.sats_in_view; }
|
||||||
|
|
||||||
|
/// Return millis() when the last GPS fix occurred (0 = never)
|
||||||
|
uint32_t getLastFixMillis() const { return lastFixMillis; }
|
||||||
|
|
||||||
bool matches(const GPSStatus *newStatus) const
|
bool matches(const GPSStatus *newStatus) const
|
||||||
{
|
{
|
||||||
#ifdef GPS_DEBUG
|
#ifdef GPS_DEBUG
|
||||||
@@ -114,6 +120,9 @@ class GPSStatus : public Status
|
|||||||
|
|
||||||
if (isDirty) {
|
if (isDirty) {
|
||||||
if (hasLock) {
|
if (hasLock) {
|
||||||
|
// Record time of last valid GPS fix
|
||||||
|
lastFixMillis = millis();
|
||||||
|
|
||||||
// In debug logs, identify position by @timestamp:stage (stage 3 = notify)
|
// In debug logs, identify position by @timestamp:stage (stage 3 = notify)
|
||||||
LOG_DEBUG("New GPS pos@%x:3 lat=%f lon=%f alt=%d pdop=%.2f track=%.2f speed=%.2f sats=%d", p.timestamp,
|
LOG_DEBUG("New GPS pos@%x:3 lat=%f lon=%f alt=%d pdop=%.2f track=%.2f speed=%.2f sats=%d", p.timestamp,
|
||||||
p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
|
p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
|
||||||
|
|||||||
+24
-11
@@ -833,16 +833,25 @@ void Power::readPowerStatus()
|
|||||||
newStatus.notifyObservers(&powerStatus2);
|
newStatus.notifyObservers(&powerStatus2);
|
||||||
#ifdef DEBUG_HEAP
|
#ifdef DEBUG_HEAP
|
||||||
if (lastheap != memGet.getFreeHeap()) {
|
if (lastheap != memGet.getFreeHeap()) {
|
||||||
std::string threadlist = "Threads running:";
|
// Use stack-allocated buffer to avoid heap allocations in monitoring code
|
||||||
|
char threadlist[256] = "Threads running:";
|
||||||
|
int threadlistLen = strlen(threadlist);
|
||||||
int running = 0;
|
int running = 0;
|
||||||
for (int i = 0; i < MAX_THREADS; i++) {
|
for (int i = 0; i < MAX_THREADS; i++) {
|
||||||
auto thread = concurrency::mainController.get(i);
|
auto thread = concurrency::mainController.get(i);
|
||||||
if ((thread != nullptr) && (thread->enabled)) {
|
if ((thread != nullptr) && (thread->enabled)) {
|
||||||
threadlist += vformat(" %s", thread->ThreadName.c_str());
|
// Use snprintf to safely append to stack buffer without heap allocation
|
||||||
|
int remaining = sizeof(threadlist) - threadlistLen - 1;
|
||||||
|
if (remaining > 0) {
|
||||||
|
int written = snprintf(threadlist + threadlistLen, remaining, " %s", thread->ThreadName.c_str());
|
||||||
|
if (written > 0 && written < remaining) {
|
||||||
|
threadlistLen += written;
|
||||||
|
}
|
||||||
|
}
|
||||||
running++;
|
running++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_DEBUG(threadlist.c_str());
|
LOG_DEBUG(threadlist);
|
||||||
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads", memGet.getFreeHeap(), memGet.getHeapSize(),
|
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads", memGet.getFreeHeap(), memGet.getHeapSize(),
|
||||||
memGet.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
memGet.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
||||||
lastheap = memGet.getFreeHeap();
|
lastheap = memGet.getFreeHeap();
|
||||||
@@ -856,15 +865,19 @@ void Power::readPowerStatus()
|
|||||||
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
|
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||||
|
|
||||||
auto newHeap = memGet.getFreeHeap();
|
auto newHeap = memGet.getFreeHeap();
|
||||||
std::string heapTopic =
|
// Use stack-allocated buffers to avoid heap allocations in monitoring code
|
||||||
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/heap/") + std::string(mac);
|
char heapTopic[128];
|
||||||
std::string heapString = std::to_string(newHeap);
|
snprintf(heapTopic, sizeof(heapTopic), "%s/2/heap/%s", (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh"), mac);
|
||||||
mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false);
|
char heapString[16];
|
||||||
|
snprintf(heapString, sizeof(heapString), "%u", newHeap);
|
||||||
|
mqtt->pubSub.publish(heapTopic, heapString, false);
|
||||||
|
|
||||||
auto wifiRSSI = WiFi.RSSI();
|
auto wifiRSSI = WiFi.RSSI();
|
||||||
std::string wifiTopic =
|
char wifiTopic[128];
|
||||||
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/wifi/") + std::string(mac);
|
snprintf(wifiTopic, sizeof(wifiTopic), "%s/2/wifi/%s", (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh"), mac);
|
||||||
std::string wifiString = std::to_string(wifiRSSI);
|
char wifiString[16];
|
||||||
mqtt->pubSub.publish(wifiTopic.c_str(), wifiString.c_str(), false);
|
snprintf(wifiString, sizeof(wifiString), "%d", wifiRSSI);
|
||||||
|
mqtt->pubSub.publish(wifiTopic, wifiString, false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
bool color = !settingsMap[ascii_logs];
|
bool color = !portduino_config.ascii_logs;
|
||||||
#else
|
#else
|
||||||
bool color = true;
|
bool color = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -99,7 +99,7 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
|
|||||||
size_t r = 0;
|
size_t r = 0;
|
||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
bool color = !settingsMap[ascii_logs];
|
bool color = !portduino_config.ascii_logs;
|
||||||
#else
|
#else
|
||||||
bool color = true;
|
bool color = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -288,7 +288,7 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
// level trace is special, two possible ways to handle it.
|
// level trace is special, two possible ways to handle it.
|
||||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
|
||||||
if (settingsStrings[traceFilename] != "") {
|
if (portduino_config.traceFilename != "") {
|
||||||
va_list arg;
|
va_list arg;
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
try {
|
try {
|
||||||
@@ -297,18 +297,18 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
}
|
}
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
}
|
}
|
||||||
if (settingsMap[logoutputlevel] < level_trace && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
|
if (portduino_config.logoutputlevel < level_trace && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
|
||||||
delete[] newFormat;
|
delete[] newFormat;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
|
if (portduino_config.logoutputlevel < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
|
||||||
delete[] newFormat;
|
delete[] newFormat;
|
||||||
return;
|
return;
|
||||||
} else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) {
|
} else if (portduino_config.logoutputlevel < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) {
|
||||||
delete[] newFormat;
|
delete[] newFormat;
|
||||||
return;
|
return;
|
||||||
} else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) {
|
} else if (portduino_config.logoutputlevel < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) {
|
||||||
delete[] newFormat;
|
delete[] newFormat;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -431,6 +431,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MESHTASTIC_EXCLUDE_SERIAL 1
|
#define MESHTASTIC_EXCLUDE_SERIAL 1
|
||||||
#define MESHTASTIC_EXCLUDE_POWERSTRESS 1
|
#define MESHTASTIC_EXCLUDE_POWERSTRESS 1
|
||||||
#define MESHTASTIC_EXCLUDE_ADMIN 1
|
#define MESHTASTIC_EXCLUDE_ADMIN 1
|
||||||
|
#define MESHTASTIC_EXCLUDE_AMBIENTLIGHTING 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
|
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ class ScanI2C
|
|||||||
LTR553ALS,
|
LTR553ALS,
|
||||||
BHI260AP,
|
BHI260AP,
|
||||||
BMM150,
|
BMM150,
|
||||||
|
TSL2561,
|
||||||
DRV2605
|
DRV2605
|
||||||
} DeviceType;
|
} DeviceType;
|
||||||
|
|
||||||
|
|||||||
@@ -461,7 +461,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address);
|
case TSL25911_ADDR:
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x12), 1);
|
||||||
|
if (registerValue == 0x50) {
|
||||||
|
type = TSL2591;
|
||||||
|
logFoundDevice("TSL25911", (uint8_t)addr.address);
|
||||||
|
} else {
|
||||||
|
type = TSL2561;
|
||||||
|
logFoundDevice("TSL2561", (uint8_t)addr.address);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
|
||||||
|
|||||||
+19
-6
@@ -808,6 +808,14 @@ bool GPS::setup()
|
|||||||
} else {
|
} else {
|
||||||
LOG_INFO("GNSS module configuration saved!");
|
LOG_INFO("GNSS module configuration saved!");
|
||||||
}
|
}
|
||||||
|
} else if (gnssModel == GNSS_MODEL_CM121) {
|
||||||
|
// only ask for RMC and GGA
|
||||||
|
// enable GGA
|
||||||
|
_serial_gps->write("$CFGMSG,0,0,1,1*1B\r\n");
|
||||||
|
delay(250);
|
||||||
|
// enable RMC
|
||||||
|
_serial_gps->write("$CFGMSG,0,4,1,1*1F\r\n");
|
||||||
|
delay(250);
|
||||||
}
|
}
|
||||||
didSerialInit = true;
|
didSerialInit = true;
|
||||||
}
|
}
|
||||||
@@ -1240,9 +1248,15 @@ GnssModel_t GPS::probe(int serialSpeed)
|
|||||||
_serial_gps->write("$PUBX,40,GSV,0,0,0,0,0,0*59\r\n");
|
_serial_gps->write("$PUBX,40,GSV,0,0,0,0,0,0*59\r\n");
|
||||||
_serial_gps->write("$PUBX,40,VTG,0,0,0,0,0,0*5E\r\n");
|
_serial_gps->write("$PUBX,40,VTG,0,0,0,0,0,0*5E\r\n");
|
||||||
delay(20);
|
delay(20);
|
||||||
|
// Close NMEA sequences on CM121
|
||||||
|
_serial_gps->write("$CFGMSG,0,1,0,1*1B\r\n");
|
||||||
|
_serial_gps->write("$CFGMSG,0,2,0,1*18\r\n");
|
||||||
|
_serial_gps->write("$CFGMSG,0,3,0,1*19\r\n");
|
||||||
|
delay(20);
|
||||||
|
|
||||||
// Unicore UFirebirdII Series: UC6580, UM620, UM621, UM670A, UM680A, or UM681A
|
// Unicore UFirebirdII Series: UC6580, UM620, UM621, UM670A, UM680A, or UM681A,or CM121
|
||||||
std::vector<ChipInfo> unicore = {{"UC6580", "UC6580", GNSS_MODEL_UC6580}, {"UM600", "UM600", GNSS_MODEL_UC6580}};
|
std::vector<ChipInfo> unicore = {
|
||||||
|
{"UC6580", "UC6580", GNSS_MODEL_UC6580}, {"UM600", "UM600", GNSS_MODEL_UC6580}, {"CM121", "CM121", GNSS_MODEL_CM121}};
|
||||||
PROBE_FAMILY("Unicore Family", "$PDTINFO", unicore, 500);
|
PROBE_FAMILY("Unicore Family", "$PDTINFO", unicore, 500);
|
||||||
|
|
||||||
std::vector<ChipInfo> atgm = {
|
std::vector<ChipInfo> atgm = {
|
||||||
@@ -1422,7 +1436,7 @@ GPS *GPS::createGps()
|
|||||||
_en_gpio = PIN_GPS_EN;
|
_en_gpio = PIN_GPS_EN;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
if (!settingsMap[has_gps])
|
if (!portduino_config.has_gps)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
|
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
|
||||||
@@ -1532,10 +1546,9 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
|||||||
t.tm_year = d.year() - 1900;
|
t.tm_year = d.year() - 1900;
|
||||||
t.tm_isdst = false;
|
t.tm_isdst = false;
|
||||||
if (t.tm_mon > -1) {
|
if (t.tm_mon > -1) {
|
||||||
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d age %d", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
|
|
||||||
t.tm_sec, ti.age());
|
|
||||||
if (perhapsSetRTC(RTCQualityGPS, t) == RTCSetResultSuccess) {
|
if (perhapsSetRTC(RTCQualityGPS, t) == RTCSetResultSuccess) {
|
||||||
LOG_DEBUG("Time set.");
|
LOG_DEBUG("NMEA GPS time set %02d-%02d-%02d %02d:%02d:%02d age %d", d.year(), d.month(), t.tm_mday, t.tm_hour,
|
||||||
|
t.tm_min, t.tm_sec, ti.age());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+2
-1
@@ -31,7 +31,8 @@ typedef enum {
|
|||||||
GNSS_MODEL_MTK_PA1616S,
|
GNSS_MODEL_MTK_PA1616S,
|
||||||
GNSS_MODEL_AG3335,
|
GNSS_MODEL_AG3335,
|
||||||
GNSS_MODEL_AG3352,
|
GNSS_MODEL_AG3352,
|
||||||
GNSS_MODEL_LS20031
|
GNSS_MODEL_LS20031,
|
||||||
|
GNSS_MODEL_CM121
|
||||||
} GnssModel_t;
|
} GnssModel_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -130,11 +130,15 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
|
|||||||
uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||||
#ifdef BUILD_EPOCH
|
#ifdef BUILD_EPOCH
|
||||||
if (tv->tv_sec < BUILD_EPOCH) {
|
if (tv->tv_sec < BUILD_EPOCH) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
||||||
|
#endif
|
||||||
return RTCSetResultInvalidTime;
|
return RTCSetResultInvalidTime;
|
||||||
} else if (tv->tv_sec > (BUILD_EPOCH + FORTY_YEARS)) {
|
} else if (tv->tv_sec > (BUILD_EPOCH + FORTY_YEARS)) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, BUILD_EPOCH,
|
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, BUILD_EPOCH,
|
||||||
BUILD_EPOCH + FORTY_YEARS);
|
BUILD_EPOCH + FORTY_YEARS);
|
||||||
|
#endif
|
||||||
return RTCSetResultInvalidTime;
|
return RTCSetResultInvalidTime;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -252,11 +256,15 @@ RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t)
|
|||||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||||
#ifdef BUILD_EPOCH
|
#ifdef BUILD_EPOCH
|
||||||
if (tv.tv_sec < BUILD_EPOCH) {
|
if (tv.tv_sec < BUILD_EPOCH) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
||||||
|
#endif
|
||||||
return RTCSetResultInvalidTime;
|
return RTCSetResultInvalidTime;
|
||||||
} else if (tv.tv_sec > (BUILD_EPOCH + FORTY_YEARS)) {
|
} else if (tv.tv_sec > (BUILD_EPOCH + FORTY_YEARS)) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, BUILD_EPOCH,
|
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, BUILD_EPOCH,
|
||||||
BUILD_EPOCH + FORTY_YEARS);
|
BUILD_EPOCH + FORTY_YEARS);
|
||||||
|
#endif
|
||||||
return RTCSetResultInvalidTime;
|
return RTCSetResultInvalidTime;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+12
-2
@@ -370,7 +370,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
|||||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||||
if (settingsMap[displayPanel] != no_screen) {
|
if (portduino_config.displayPanel != no_screen) {
|
||||||
LOG_DEBUG("Make TFTDisplay!");
|
LOG_DEBUG("Make TFTDisplay!");
|
||||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||||
@@ -618,7 +618,7 @@ void Screen::setup()
|
|||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||||
if (settingsMap[touchscreenModule]) {
|
if (portduino_config.touchscreenModule) {
|
||||||
touchScreenImpl1 =
|
touchScreenImpl1 =
|
||||||
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
||||||
touchScreenImpl1->init();
|
touchScreenImpl1->init();
|
||||||
@@ -1018,6 +1018,11 @@ void Screen::setFrames(FrameFocus focus)
|
|||||||
indicatorIcons.push_back(digital_icon_clock);
|
indicatorIcons.push_back(digital_icon_clock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (!hiddenFrames.chirpy) {
|
||||||
|
fsi.positions.chirpy = numframes;
|
||||||
|
normalFrames[numframes++] = graphics::DebugRenderer::drawChirpy;
|
||||||
|
indicatorIcons.push_back(small_chirpy);
|
||||||
|
}
|
||||||
|
|
||||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||||
if (!hiddenFrames.wifi && isWifiAvailable()) {
|
if (!hiddenFrames.wifi && isWifiAvailable()) {
|
||||||
@@ -1186,6 +1191,9 @@ void Screen::toggleFrameVisibility(const std::string &frameName)
|
|||||||
if (frameName == "show_favorites") {
|
if (frameName == "show_favorites") {
|
||||||
hiddenFrames.show_favorites = !hiddenFrames.show_favorites;
|
hiddenFrames.show_favorites = !hiddenFrames.show_favorites;
|
||||||
}
|
}
|
||||||
|
if (frameName == "chirpy") {
|
||||||
|
hiddenFrames.chirpy = !hiddenFrames.chirpy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Screen::isFrameHidden(const std::string &frameName) const
|
bool Screen::isFrameHidden(const std::string &frameName) const
|
||||||
@@ -1214,6 +1222,8 @@ bool Screen::isFrameHidden(const std::string &frameName) const
|
|||||||
return hiddenFrames.clock;
|
return hiddenFrames.clock;
|
||||||
if (frameName == "show_favorites")
|
if (frameName == "show_favorites")
|
||||||
return hiddenFrames.show_favorites;
|
return hiddenFrames.show_favorites;
|
||||||
|
if (frameName == "chirpy")
|
||||||
|
return hiddenFrames.chirpy;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -669,6 +669,7 @@ class Screen : public concurrency::OSThread
|
|||||||
uint8_t nodelist_distance = 255;
|
uint8_t nodelist_distance = 255;
|
||||||
uint8_t nodelist_bearings = 255;
|
uint8_t nodelist_bearings = 255;
|
||||||
uint8_t clock = 255;
|
uint8_t clock = 255;
|
||||||
|
uint8_t chirpy = 255;
|
||||||
uint8_t firstFavorite = 255;
|
uint8_t firstFavorite = 255;
|
||||||
uint8_t lastFavorite = 255;
|
uint8_t lastFavorite = 255;
|
||||||
uint8_t lora = 255;
|
uint8_t lora = 255;
|
||||||
@@ -698,6 +699,7 @@ class Screen : public concurrency::OSThread
|
|||||||
#endif
|
#endif
|
||||||
bool lora = false;
|
bool lora = false;
|
||||||
bool show_favorites = false;
|
bool show_favorites = false;
|
||||||
|
bool chirpy = true;
|
||||||
} hiddenFrames;
|
} hiddenFrames;
|
||||||
|
|
||||||
/// Try to start drawing ASAP
|
/// Try to start drawing ASAP
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "graphics/SharedUIDisplay.h"
|
#include "graphics/SharedUIDisplay.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
|
#include "graphics/draw/UIRenderer.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "meshtastic/config.pb.h"
|
#include "meshtastic/config.pb.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
@@ -16,6 +17,10 @@ void determineResolution(int16_t screenheight, int16_t screenwidth)
|
|||||||
isHighResolution = true;
|
isHighResolution = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (screenwidth > 128 && screenheight <= 64) {
|
||||||
|
isHighResolution = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Special case for Heltec Wireless Tracker v1.1
|
// Special case for Heltec Wireless Tracker v1.1
|
||||||
if (screenwidth == 160 && screenheight == 80) {
|
if (screenwidth == 160 && screenheight == 80) {
|
||||||
isHighResolution = false;
|
isHighResolution = false;
|
||||||
@@ -53,7 +58,7 @@ void drawRoundedHighlight(OLEDDisplay *display, int16_t x, int16_t y, int16_t w,
|
|||||||
// *************************
|
// *************************
|
||||||
// * Common Header Drawing *
|
// * Common Header Drawing *
|
||||||
// *************************
|
// *************************
|
||||||
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr, bool battery_only)
|
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr, bool force_no_invert, bool show_date)
|
||||||
{
|
{
|
||||||
constexpr int HEADER_OFFSET_Y = 1;
|
constexpr int HEADER_OFFSET_Y = 1;
|
||||||
y += HEADER_OFFSET_Y;
|
y += HEADER_OFFSET_Y;
|
||||||
@@ -69,7 +74,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
const int screenW = display->getWidth();
|
const int screenW = display->getWidth();
|
||||||
const int screenH = display->getHeight();
|
const int screenH = display->getHeight();
|
||||||
|
|
||||||
if (!battery_only) {
|
if (!force_no_invert) {
|
||||||
// === Inverted Header Background ===
|
// === Inverted Header Background ===
|
||||||
if (isInverted) {
|
if (isInverted) {
|
||||||
display->setColor(BLACK);
|
display->setColor(BLACK);
|
||||||
@@ -187,13 +192,28 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
int timeStrWidth = display->getStringWidth("12:34"); // Default alignment
|
int timeStrWidth = display->getStringWidth("12:34"); // Default alignment
|
||||||
int timeX = screenW - xOffset - timeStrWidth + 4;
|
int timeX = screenW - xOffset - timeStrWidth + 4;
|
||||||
|
|
||||||
if (rtc_sec > 0 && !battery_only) {
|
if (rtc_sec > 0) {
|
||||||
// === Build Time String ===
|
// === Build Time String ===
|
||||||
long hms = (rtc_sec % SEC_PER_DAY + SEC_PER_DAY) % SEC_PER_DAY;
|
long hms = (rtc_sec % SEC_PER_DAY + SEC_PER_DAY) % SEC_PER_DAY;
|
||||||
int hour = hms / SEC_PER_HOUR;
|
int hour = hms / SEC_PER_HOUR;
|
||||||
int minute = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
int minute = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||||
snprintf(timeStr, sizeof(timeStr), "%d:%02d", hour, minute);
|
snprintf(timeStr, sizeof(timeStr), "%d:%02d", hour, minute);
|
||||||
|
|
||||||
|
// === Build Date String ===
|
||||||
|
char datetimeStr[25];
|
||||||
|
UIRenderer::formatDateTime(datetimeStr, sizeof(datetimeStr), rtc_sec, display, false);
|
||||||
|
char dateLine[40];
|
||||||
|
|
||||||
|
if (isHighResolution) {
|
||||||
|
snprintf(dateLine, sizeof(dateLine), "%s", datetimeStr);
|
||||||
|
} else {
|
||||||
|
if (hasUnreadMessage) {
|
||||||
|
snprintf(dateLine, sizeof(dateLine), "%s", &datetimeStr[5]);
|
||||||
|
} else {
|
||||||
|
snprintf(dateLine, sizeof(dateLine), "%s", &datetimeStr[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (config.display.use_12h_clock) {
|
if (config.display.use_12h_clock) {
|
||||||
bool isPM = hour >= 12;
|
bool isPM = hour >= 12;
|
||||||
hour %= 12;
|
hour %= 12;
|
||||||
@@ -202,7 +222,11 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
snprintf(timeStr, sizeof(timeStr), "%d:%02d%s", hour, minute, isPM ? "p" : "a");
|
snprintf(timeStr, sizeof(timeStr), "%d:%02d%s", hour, minute, isPM ? "p" : "a");
|
||||||
}
|
}
|
||||||
|
|
||||||
timeStrWidth = display->getStringWidth(timeStr);
|
if (show_date) {
|
||||||
|
timeStrWidth = display->getStringWidth(dateLine);
|
||||||
|
} else {
|
||||||
|
timeStrWidth = display->getStringWidth(timeStr);
|
||||||
|
}
|
||||||
timeX = screenW - xOffset - timeStrWidth + 3;
|
timeX = screenW - xOffset - timeStrWidth + 3;
|
||||||
|
|
||||||
// === Show Mail or Mute Icon to the Left of Time ===
|
// === Show Mail or Mute Icon to the Left of Time ===
|
||||||
@@ -229,7 +253,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
int iconW = 16, iconH = 12;
|
int iconW = 16, iconH = 12;
|
||||||
int iconX = iconRightEdge - iconW;
|
int iconX = iconRightEdge - iconW;
|
||||||
int iconY = textY + (FONT_HEIGHT_SMALL - iconH) / 2 - 1;
|
int iconY = textY + (FONT_HEIGHT_SMALL - iconH) / 2 - 1;
|
||||||
if (isInverted) {
|
if (isInverted && !force_no_invert) {
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
display->fillRect(iconX - 1, iconY - 1, iconW + 3, iconH + 2);
|
display->fillRect(iconX - 1, iconY - 1, iconW + 3, iconH + 2);
|
||||||
display->setColor(BLACK);
|
display->setColor(BLACK);
|
||||||
@@ -244,7 +268,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
} else {
|
} else {
|
||||||
int iconX = iconRightEdge - (mail_width - 2);
|
int iconX = iconRightEdge - (mail_width - 2);
|
||||||
int iconY = textY + (FONT_HEIGHT_SMALL - mail_height) / 2;
|
int iconY = textY + (FONT_HEIGHT_SMALL - mail_height) / 2;
|
||||||
if (isInverted) {
|
if (isInverted && !force_no_invert) {
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
display->fillRect(iconX - 1, iconY - 1, mail_width + 2, mail_height + 2);
|
display->fillRect(iconX - 1, iconY - 1, mail_width + 2, mail_height + 2);
|
||||||
display->setColor(BLACK);
|
display->setColor(BLACK);
|
||||||
@@ -287,10 +311,17 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Draw Time ===
|
if (show_date) {
|
||||||
display->drawString(timeX, textY, timeStr);
|
// === Draw Date ===
|
||||||
if (isBold)
|
display->drawString(timeX, textY, dateLine);
|
||||||
display->drawString(timeX - 1, textY, timeStr);
|
if (isBold)
|
||||||
|
display->drawString(timeX - 1, textY, dateLine);
|
||||||
|
} else {
|
||||||
|
// === Draw Time ===
|
||||||
|
display->drawString(timeX, textY, timeStr);
|
||||||
|
if (isBold)
|
||||||
|
display->drawString(timeX - 1, textY, timeStr);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// === No Time Available: Mail/Mute Icon Moves to Far Right ===
|
// === No Time Available: Mail/Mute Icon Moves to Far Right ===
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ void determineResolution(int16_t screenheight, int16_t screenwidth);
|
|||||||
void drawRoundedHighlight(OLEDDisplay *display, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r);
|
void drawRoundedHighlight(OLEDDisplay *display, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r);
|
||||||
|
|
||||||
// Shared battery/time/mail header
|
// Shared battery/time/mail header
|
||||||
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr = "", bool battery_only = false);
|
void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr = "", bool force_no_invert = false,
|
||||||
|
bool show_date = false);
|
||||||
|
|
||||||
const int *getTextPositions(OLEDDisplay *display);
|
const int *getTextPositions(OLEDDisplay *display);
|
||||||
|
|
||||||
|
|||||||
+53
-44
@@ -767,24 +767,24 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
|
|
||||||
LGFX(void)
|
LGFX(void)
|
||||||
{
|
{
|
||||||
if (settingsMap[displayPanel] == st7789)
|
if (portduino_config.displayPanel == st7789)
|
||||||
_panel_instance = new lgfx::Panel_ST7789;
|
_panel_instance = new lgfx::Panel_ST7789;
|
||||||
else if (settingsMap[displayPanel] == st7735)
|
else if (portduino_config.displayPanel == st7735)
|
||||||
_panel_instance = new lgfx::Panel_ST7735;
|
_panel_instance = new lgfx::Panel_ST7735;
|
||||||
else if (settingsMap[displayPanel] == st7735s)
|
else if (portduino_config.displayPanel == st7735s)
|
||||||
_panel_instance = new lgfx::Panel_ST7735S;
|
_panel_instance = new lgfx::Panel_ST7735S;
|
||||||
else if (settingsMap[displayPanel] == st7796)
|
else if (portduino_config.displayPanel == st7796)
|
||||||
_panel_instance = new lgfx::Panel_ST7796;
|
_panel_instance = new lgfx::Panel_ST7796;
|
||||||
else if (settingsMap[displayPanel] == ili9341)
|
else if (portduino_config.displayPanel == ili9341)
|
||||||
_panel_instance = new lgfx::Panel_ILI9341;
|
_panel_instance = new lgfx::Panel_ILI9341;
|
||||||
else if (settingsMap[displayPanel] == ili9342)
|
else if (portduino_config.displayPanel == ili9342)
|
||||||
_panel_instance = new lgfx::Panel_ILI9342;
|
_panel_instance = new lgfx::Panel_ILI9342;
|
||||||
else if (settingsMap[displayPanel] == ili9488)
|
else if (portduino_config.displayPanel == ili9488)
|
||||||
_panel_instance = new lgfx::Panel_ILI9488;
|
_panel_instance = new lgfx::Panel_ILI9488;
|
||||||
else if (settingsMap[displayPanel] == hx8357d)
|
else if (portduino_config.displayPanel == hx8357d)
|
||||||
_panel_instance = new lgfx::Panel_HX8357D;
|
_panel_instance = new lgfx::Panel_HX8357D;
|
||||||
#if defined(LGFX_SDL)
|
#if defined(LGFX_SDL)
|
||||||
else if (settingsMap[displayPanel] == x11) {
|
else if (portduino_config.displayPanel == x11) {
|
||||||
_panel_instance = new lgfx::Panel_sdl;
|
_panel_instance = new lgfx::Panel_sdl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -795,61 +795,61 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
|
|
||||||
auto buscfg = _bus_instance.config();
|
auto buscfg = _bus_instance.config();
|
||||||
buscfg.spi_mode = 0;
|
buscfg.spi_mode = 0;
|
||||||
buscfg.spi_host = settingsMap[displayspidev];
|
buscfg.spi_host = portduino_config.display_spi_dev_int;
|
||||||
|
|
||||||
buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable)
|
buscfg.pin_dc = portduino_config.displayDC.pin; // Set SPI DC pin number (-1 = disable)
|
||||||
|
|
||||||
_bus_instance.config(buscfg); // applies the set value to the bus.
|
_bus_instance.config(buscfg); // applies the set value to the bus.
|
||||||
_panel_instance->setBus(&_bus_instance); // set the bus on the panel.
|
_panel_instance->setBus(&_bus_instance); // set the bus on the panel.
|
||||||
|
|
||||||
auto cfg = _panel_instance->config(); // Gets a structure for display panel settings.
|
auto cfg = _panel_instance->config(); // Gets a structure for display panel settings.
|
||||||
LOG_DEBUG("Width: %d, Height: %d", settingsMap[displayWidth], settingsMap[displayHeight]);
|
LOG_DEBUG("Width: %d, Height: %d", portduino_config.displayWidth, portduino_config.displayHeight);
|
||||||
cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable)
|
cfg.pin_cs = portduino_config.displayCS.pin; // Pin number where CS is connected (-1 = disable)
|
||||||
cfg.pin_rst = settingsMap[displayReset];
|
cfg.pin_rst = portduino_config.displayReset.pin;
|
||||||
if (settingsMap[displayRotate]) {
|
if (portduino_config.displayRotate) {
|
||||||
cfg.panel_width = settingsMap[displayHeight]; // actual displayable width
|
cfg.panel_width = portduino_config.displayHeight; // actual displayable width
|
||||||
cfg.panel_height = settingsMap[displayWidth]; // actual displayable height
|
cfg.panel_height = portduino_config.displayWidth; // actual displayable height
|
||||||
} else {
|
} else {
|
||||||
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
|
cfg.panel_width = portduino_config.displayWidth; // actual displayable width
|
||||||
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
|
cfg.panel_height = portduino_config.displayHeight; // actual displayable height
|
||||||
}
|
}
|
||||||
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
|
cfg.offset_x = portduino_config.displayOffsetX; // Panel offset amount in X direction
|
||||||
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
|
cfg.offset_y = portduino_config.displayOffsetY; // Panel offset amount in Y direction
|
||||||
cfg.offset_rotation = settingsMap[displayOffsetRotate]; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
cfg.offset_rotation = portduino_config.displayOffsetRotate; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||||
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
|
cfg.invert = portduino_config.displayInvert; // Set to true if the light/darkness of the panel is reversed
|
||||||
|
|
||||||
_panel_instance->config(cfg);
|
_panel_instance->config(cfg);
|
||||||
|
|
||||||
// Configure settings for touch control.
|
// Configure settings for touch control.
|
||||||
if (settingsMap[touchscreenModule]) {
|
if (portduino_config.touchscreenModule) {
|
||||||
if (settingsMap[touchscreenModule] == xpt2046) {
|
if (portduino_config.touchscreenModule == xpt2046) {
|
||||||
_touch_instance = new lgfx::Touch_XPT2046;
|
_touch_instance = new lgfx::Touch_XPT2046;
|
||||||
} else if (settingsMap[touchscreenModule] == stmpe610) {
|
} else if (portduino_config.touchscreenModule == stmpe610) {
|
||||||
_touch_instance = new lgfx::Touch_STMPE610;
|
_touch_instance = new lgfx::Touch_STMPE610;
|
||||||
} else if (settingsMap[touchscreenModule] == ft5x06) {
|
} else if (portduino_config.touchscreenModule == ft5x06) {
|
||||||
_touch_instance = new lgfx::Touch_FT5x06;
|
_touch_instance = new lgfx::Touch_FT5x06;
|
||||||
}
|
}
|
||||||
auto touch_cfg = _touch_instance->config();
|
auto touch_cfg = _touch_instance->config();
|
||||||
|
|
||||||
touch_cfg.pin_cs = settingsMap[touchscreenCS];
|
touch_cfg.pin_cs = portduino_config.touchscreenCS.pin;
|
||||||
touch_cfg.x_min = 0;
|
touch_cfg.x_min = 0;
|
||||||
touch_cfg.x_max = settingsMap[displayHeight] - 1;
|
touch_cfg.x_max = portduino_config.displayHeight - 1;
|
||||||
touch_cfg.y_min = 0;
|
touch_cfg.y_min = 0;
|
||||||
touch_cfg.y_max = settingsMap[displayWidth] - 1;
|
touch_cfg.y_max = portduino_config.displayWidth - 1;
|
||||||
touch_cfg.pin_int = settingsMap[touchscreenIRQ];
|
touch_cfg.pin_int = portduino_config.touchscreenIRQ.pin;
|
||||||
touch_cfg.bus_shared = true;
|
touch_cfg.bus_shared = true;
|
||||||
touch_cfg.offset_rotation = settingsMap[touchscreenRotate];
|
touch_cfg.offset_rotation = portduino_config.touchscreenRotate;
|
||||||
if (settingsMap[touchscreenI2CAddr] != -1) {
|
if (portduino_config.touchscreenI2CAddr != -1) {
|
||||||
touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr];
|
touch_cfg.i2c_addr = portduino_config.touchscreenI2CAddr;
|
||||||
} else {
|
} else {
|
||||||
touch_cfg.spi_host = settingsMap[touchscreenspidev];
|
touch_cfg.spi_host = portduino_config.touchscreen_spi_dev_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
_touch_instance->config(touch_cfg);
|
_touch_instance->config(touch_cfg);
|
||||||
_panel_instance->setTouch(_touch_instance);
|
_panel_instance->setTouch(_touch_instance);
|
||||||
}
|
}
|
||||||
#if defined(LGFX_SDL)
|
#if defined(LGFX_SDL)
|
||||||
if (settingsMap[displayPanel] == x11) {
|
if (portduino_config.displayPanel == x11) {
|
||||||
lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)_panel_instance;
|
lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)_panel_instance;
|
||||||
sdl_panel_->setup();
|
sdl_panel_->setup();
|
||||||
sdl_panel_->addKeyCodeMapping(SDLK_RETURN, SDL_SCANCODE_KP_ENTER);
|
sdl_panel_->addKeyCodeMapping(SDLK_RETURN, SDL_SCANCODE_KP_ENTER);
|
||||||
@@ -1115,10 +1115,10 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
|
|||||||
backlightEnable = p;
|
backlightEnable = p;
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[displayRotate]) {
|
if (portduino_config.displayRotate) {
|
||||||
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayWidth], settingsMap[configNames::displayHeight]);
|
setGeometry(GEOMETRY_RAWMODE, portduino_config.displayWidth, portduino_config.displayWidth);
|
||||||
} else {
|
} else {
|
||||||
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]);
|
setGeometry(GEOMETRY_RAWMODE, portduino_config.displayHeight, portduino_config.displayHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(SCREEN_ROTATE)
|
#elif defined(SCREEN_ROTATE)
|
||||||
@@ -1128,6 +1128,15 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TFTDisplay::~TFTDisplay()
|
||||||
|
{
|
||||||
|
// Clean up allocated line pixel buffer to prevent memory leak
|
||||||
|
if (linePixelBuffer != nullptr) {
|
||||||
|
free(linePixelBuffer);
|
||||||
|
linePixelBuffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write the buffer to the display memory
|
// Write the buffer to the display memory
|
||||||
void TFTDisplay::display(bool fromBlank)
|
void TFTDisplay::display(bool fromBlank)
|
||||||
{
|
{
|
||||||
@@ -1231,7 +1240,7 @@ void TFTDisplay::sdlLoop()
|
|||||||
#if defined(LGFX_SDL)
|
#if defined(LGFX_SDL)
|
||||||
static int lastPressed = 0;
|
static int lastPressed = 0;
|
||||||
static int shuttingDown = false;
|
static int shuttingDown = false;
|
||||||
if (settingsMap[displayPanel] == x11) {
|
if (portduino_config.displayPanel == x11) {
|
||||||
lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)tft->_panel_instance;
|
lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)tft->_panel_instance;
|
||||||
if (sdl_panel_->loop() && !shuttingDown) {
|
if (sdl_panel_->loop() && !shuttingDown) {
|
||||||
LOG_WARN("Window Closed!");
|
LOG_WARN("Window Closed!");
|
||||||
@@ -1279,8 +1288,8 @@ void TFTDisplay::sendCommand(uint8_t com)
|
|||||||
backlightEnable->set(true);
|
backlightEnable->set(true);
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
display(true);
|
display(true);
|
||||||
if (settingsMap[displayBacklight] > 0)
|
if (portduino_config.displayBacklight.pin > 0)
|
||||||
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON);
|
digitalWrite(portduino_config.displayBacklight.pin, TFT_BACKLIGHT_ON);
|
||||||
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
|
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
|
||||||
tft->wakeup();
|
tft->wakeup();
|
||||||
tft->powerSaveOff();
|
tft->powerSaveOff();
|
||||||
@@ -1303,8 +1312,8 @@ void TFTDisplay::sendCommand(uint8_t com)
|
|||||||
backlightEnable->set(false);
|
backlightEnable->set(false);
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
tft->clear();
|
tft->clear();
|
||||||
if (settingsMap[displayBacklight] > 0)
|
if (portduino_config.displayBacklight.pin > 0)
|
||||||
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON);
|
digitalWrite(portduino_config.displayBacklight.pin, !TFT_BACKLIGHT_ON);
|
||||||
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
|
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
|
||||||
tft->sleep();
|
tft->sleep();
|
||||||
tft->powerSaveOn();
|
tft->powerSaveOn();
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ class TFTDisplay : public OLEDDisplay
|
|||||||
*/
|
*/
|
||||||
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||||
|
|
||||||
|
// Destructor to clean up allocated memory
|
||||||
|
~TFTDisplay();
|
||||||
|
|
||||||
// Write the buffer to the display memory
|
// Write the buffer to the display memory
|
||||||
virtual void display() override { display(false); };
|
virtual void display() override { display(false); };
|
||||||
virtual void display(bool fromBlank);
|
virtual void display(bool fromBlank);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#if HAS_SCREEN
|
#if HAS_SCREEN
|
||||||
#include "ClockRenderer.h"
|
#include "ClockRenderer.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "UIRenderer.h"
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "gps/GeoCoord.h"
|
#include "gps/GeoCoord.h"
|
||||||
#include "gps/RTC.h"
|
#include "gps/RTC.h"
|
||||||
@@ -190,7 +189,7 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
// === Set Title, Blank for Clock
|
// === Set Title, Blank for Clock
|
||||||
const char *titleStr = "";
|
const char *titleStr = "";
|
||||||
// === Header ===
|
// === Header ===
|
||||||
graphics::drawCommonHeader(display, x, y, titleStr, true);
|
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
||||||
@@ -294,6 +293,7 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
display->drawString(startingHourMinuteTextX + xOffset, (display->getHeight() - hourMinuteTextY) - yOffset - 2,
|
display->drawString(startingHourMinuteTextX + xOffset, (display->getHeight() - hourMinuteTextY) - yOffset - 2,
|
||||||
isPM ? "pm" : "am");
|
isPM ? "pm" : "am");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_EINK
|
#ifndef USE_EINK
|
||||||
xOffset = (isHighResolution) ? 18 : 10;
|
xOffset = (isHighResolution) ? 18 : 10;
|
||||||
display->drawString(startingHourMinuteTextX + timeStringWidth - xOffset, (display->getHeight() - hourMinuteTextY) - yOffset,
|
display->drawString(startingHourMinuteTextX + timeStringWidth - xOffset, (display->getHeight() - hourMinuteTextY) - yOffset,
|
||||||
@@ -313,7 +313,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
// === Set Title, Blank for Clock
|
// === Set Title, Blank for Clock
|
||||||
const char *titleStr = "";
|
const char *titleStr = "";
|
||||||
// === Header ===
|
// === Header ===
|
||||||
graphics::drawCommonHeader(display, x, y, titleStr, true);
|
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
||||||
|
|||||||
@@ -391,18 +391,27 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
int nameX = (SCREEN_WIDTH - textWidth);
|
int nameX = (SCREEN_WIDTH - textWidth);
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
||||||
|
|
||||||
// === Second Row: Radio Preset ===
|
// === Second Row: Role ===
|
||||||
|
auto role = DisplayFormatters::getDeviceRole(config.device.role);
|
||||||
|
char device_role[25];
|
||||||
|
snprintf(device_role, sizeof(device_role), "Role: %s", role);
|
||||||
|
textWidth = display->getStringWidth(device_role);
|
||||||
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
|
display->drawString(nameX, getTextPositions(display)[line++], device_role);
|
||||||
|
|
||||||
|
// === Third Row: Radio Preset ===
|
||||||
auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false, config.lora.use_preset);
|
auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false, config.lora.use_preset);
|
||||||
|
|
||||||
char regionradiopreset[25];
|
char regionradiopreset[25];
|
||||||
const char *region = myRegion ? myRegion->name : NULL;
|
const char *region = myRegion ? myRegion->name : NULL;
|
||||||
if (region != nullptr) {
|
if (region != nullptr) {
|
||||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s/%s", region, mode);
|
snprintf(regionradiopreset, sizeof(regionradiopreset), "Reg: %s/%s", region, mode);
|
||||||
}
|
}
|
||||||
textWidth = display->getStringWidth(regionradiopreset);
|
textWidth = display->getStringWidth(regionradiopreset);
|
||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], regionradiopreset);
|
display->drawString(nameX, getTextPositions(display)[line++], regionradiopreset);
|
||||||
|
|
||||||
// === Third Row: Frequency / ChanNum ===
|
// === Fourth Row: Frequency / ChanNum ===
|
||||||
char frequencyslot[35];
|
char frequencyslot[35];
|
||||||
char freqStr[16];
|
char freqStr[16];
|
||||||
float freq = RadioLibInterface::instance->getFreq();
|
float freq = RadioLibInterface::instance->getFreq();
|
||||||
@@ -420,7 +429,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], frequencyslot);
|
display->drawString(nameX, getTextPositions(display)[line++], frequencyslot);
|
||||||
|
|
||||||
// === Fourth Row: Channel Utilization ===
|
// === Fifth Row: Channel Utilization ===
|
||||||
const char *chUtil = "ChUtil:";
|
const char *chUtil = "ChUtil:";
|
||||||
char chUtilPercentage[10];
|
char chUtilPercentage[10];
|
||||||
snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent());
|
snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent());
|
||||||
@@ -437,7 +446,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
int total_line_content_width = (chUtil_x + chutil_bar_width + display->getStringWidth(chUtilPercentage) + extraoffset) / 2;
|
int total_line_content_width = (chUtil_x + chutil_bar_width + display->getStringWidth(chUtilPercentage) + extraoffset) / 2;
|
||||||
int starting_position = centerofscreen - total_line_content_width;
|
int starting_position = centerofscreen - total_line_content_width;
|
||||||
|
|
||||||
display->drawString(starting_position, getTextPositions(display)[line++], chUtil);
|
display->drawString(starting_position, getTextPositions(display)[line], chUtil);
|
||||||
|
|
||||||
// Force 56% or higher to show a full 100% bar, text would still show related percent.
|
// Force 56% or higher to show a full 100% bar, text would still show related percent.
|
||||||
if (chutil_percent >= 61) {
|
if (chutil_percent >= 61) {
|
||||||
@@ -474,7 +483,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
display->fillRect(starting_position + chUtil_x, chUtil_y, fillRight, chutil_bar_height);
|
display->fillRect(starting_position + chUtil_x, chUtil_y, fillRight, chutil_bar_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, getTextPositions(display)[4],
|
display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, getTextPositions(display)[line++],
|
||||||
chUtilPercentage);
|
chUtilPercentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,6 +634,33 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
display->drawString(nameX, getTextPositions(display)[line], uptimeStr);
|
display->drawString(nameX, getTextPositions(display)[line], uptimeStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ****************************
|
||||||
|
// * Chirpy Screen *
|
||||||
|
// ****************************
|
||||||
|
void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->clear();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
int line = 1;
|
||||||
|
int iconX = SCREEN_WIDTH - chirpy_width - (chirpy_width / 3);
|
||||||
|
int iconY = (SCREEN_HEIGHT - chirpy_height) / 2;
|
||||||
|
int textX_offset = 10;
|
||||||
|
if (isHighResolution) {
|
||||||
|
iconX = SCREEN_WIDTH - chirpy_width_hirez - (chirpy_width_hirez / 3);
|
||||||
|
iconY = (SCREEN_HEIGHT - chirpy_height_hirez) / 2;
|
||||||
|
textX_offset = textX_offset * 4;
|
||||||
|
display->drawXbm(iconX, iconY, chirpy_width_hirez, chirpy_height_hirez, chirpy_hirez);
|
||||||
|
} else {
|
||||||
|
display->drawXbm(iconX, iconY, chirpy_width, chirpy_height, chirpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
int textX = (display->getWidth() / 2) - textX_offset - (display->getStringWidth("Hello") / 2);
|
||||||
|
display->drawString(textX, getTextPositions(display)[line++], "Hello");
|
||||||
|
textX = (display->getWidth() / 2) - textX_offset - (display->getStringWidth("World!") / 2);
|
||||||
|
display->drawString(textX, getTextPositions(display)[line++], "World!");
|
||||||
|
}
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#endif
|
#endif
|
||||||
@@ -33,6 +33,9 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
|
|
||||||
// System screen display
|
// System screen display
|
||||||
void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
|
|
||||||
|
// Chirpy screen display
|
||||||
|
void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
@@ -31,17 +31,19 @@ uint8_t test_count = 0;
|
|||||||
|
|
||||||
void menuHandler::loraMenu()
|
void menuHandler::loraMenu()
|
||||||
{
|
{
|
||||||
static const char *optionsArray[] = {"Back", "Region Picker"};
|
static const char *optionsArray[] = {"Back", "Region Picker", "Device Role"};
|
||||||
enum optionsNumbers { Back = 0, lora_picker = 1 };
|
enum optionsNumbers { Back = 0, lora_picker = 1, device_role_picker = 2 };
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "LoRa Actions";
|
bannerOptions.message = "LoRa Actions";
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 2;
|
bannerOptions.optionsCount = 3;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == Back) {
|
if (selected == Back) {
|
||||||
// No action
|
// No action
|
||||||
} else if (selected == lora_picker) {
|
} else if (selected == lora_picker) {
|
||||||
menuHandler::menuQueue = menuHandler::lora_picker;
|
menuHandler::menuQueue = menuHandler::lora_picker;
|
||||||
|
} else if (selected == device_role_picker) {
|
||||||
|
menuHandler::menuQueue = menuHandler::device_role_picker;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
@@ -140,6 +142,40 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
|
|||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menuHandler::DeviceRolePicker()
|
||||||
|
{
|
||||||
|
static const char *optionsArray[] = {"Back", "Client", "Client Mute", "Lost and Found", "Tracker"};
|
||||||
|
enum optionsNumbers {
|
||||||
|
Back = 0,
|
||||||
|
devicerole_client = 1,
|
||||||
|
devicerole_clientmute = 2,
|
||||||
|
devicerole_lostandfound = 3,
|
||||||
|
devicerole_tracker = 4
|
||||||
|
};
|
||||||
|
BannerOverlayOptions bannerOptions;
|
||||||
|
bannerOptions.message = "Device Role";
|
||||||
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
|
bannerOptions.optionsCount = 5;
|
||||||
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
|
if (selected == Back) {
|
||||||
|
menuHandler::menuQueue = menuHandler::lora_Menu;
|
||||||
|
screen->runNow();
|
||||||
|
return;
|
||||||
|
} else if (selected == devicerole_client) {
|
||||||
|
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
|
||||||
|
} else if (selected == devicerole_clientmute) {
|
||||||
|
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE;
|
||||||
|
} else if (selected == devicerole_lostandfound) {
|
||||||
|
config.device.role = meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND;
|
||||||
|
} else if (selected == devicerole_tracker) {
|
||||||
|
config.device.role = meshtastic_Config_DeviceConfig_Role_TRACKER;
|
||||||
|
}
|
||||||
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
|
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
|
||||||
|
};
|
||||||
|
screen->showOverlayBanner(bannerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
void menuHandler::TwelveHourPicker()
|
void menuHandler::TwelveHourPicker()
|
||||||
{
|
{
|
||||||
static const char *optionsArray[] = {"Back", "12-hour", "24-hour"};
|
static const char *optionsArray[] = {"Back", "12-hour", "24-hour"};
|
||||||
@@ -968,16 +1004,33 @@ void menuHandler::traceRouteMenu()
|
|||||||
void menuHandler::testMenu()
|
void menuHandler::testMenu()
|
||||||
{
|
{
|
||||||
|
|
||||||
static const char *optionsArray[] = {"Back", "Number Picker"};
|
enum optionsNumbers { Back, NumberPicker, ShowChirpy };
|
||||||
|
static const char *optionsArray[4] = {"Back"};
|
||||||
|
static int optionsEnumArray[4] = {Back};
|
||||||
|
int options = 1;
|
||||||
|
|
||||||
|
optionsArray[options] = "Number Picker";
|
||||||
|
optionsEnumArray[options++] = NumberPicker;
|
||||||
|
|
||||||
|
optionsArray[options] = screen->isFrameHidden("chirpy") ? "Show Chirpy" : "Hide Chirpy";
|
||||||
|
optionsEnumArray[options++] = ShowChirpy;
|
||||||
|
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
std::string message = "Test to Run?\n";
|
bannerOptions.message = "Hidden Test Menu";
|
||||||
bannerOptions.message = message.c_str();
|
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 2;
|
bannerOptions.optionsCount = options;
|
||||||
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == 1) {
|
if (selected == NumberPicker) {
|
||||||
menuQueue = number_test;
|
menuQueue = number_test;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
|
} else if (selected == ShowChirpy) {
|
||||||
|
screen->toggleFrameVisibility("chirpy");
|
||||||
|
screen->setFrames(Screen::FOCUS_SYSTEM);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
menuQueue = system_base_menu;
|
||||||
|
screen->runNow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
@@ -1232,7 +1285,7 @@ void menuHandler::FrameToggles_menu()
|
|||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
bannerOptions.InitialSelected = lastSelectedIndex; // Use index, not enum value
|
bannerOptions.InitialSelected = lastSelectedIndex; // Use index, not enum value
|
||||||
|
|
||||||
bannerOptions.bannerCallback = [optionsEnumArray, options](int selected) mutable -> void {
|
bannerOptions.bannerCallback = [options](int selected) mutable -> void {
|
||||||
// Find the index of selected in optionsEnumArray
|
// Find the index of selected in optionsEnumArray
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (; idx < options; ++idx) {
|
for (; idx < options; ++idx) {
|
||||||
@@ -1291,9 +1344,15 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
|||||||
switch (menuQueue) {
|
switch (menuQueue) {
|
||||||
case menu_none:
|
case menu_none:
|
||||||
break;
|
break;
|
||||||
|
case lora_Menu:
|
||||||
|
loraMenu();
|
||||||
|
break;
|
||||||
case lora_picker:
|
case lora_picker:
|
||||||
LoraRegionPicker();
|
LoraRegionPicker();
|
||||||
break;
|
break;
|
||||||
|
case device_role_picker:
|
||||||
|
DeviceRolePicker();
|
||||||
|
break;
|
||||||
case no_timeout_lora_picker:
|
case no_timeout_lora_picker:
|
||||||
LoraRegionPicker(0);
|
LoraRegionPicker(0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ class menuHandler
|
|||||||
public:
|
public:
|
||||||
enum screenMenus {
|
enum screenMenus {
|
||||||
menu_none,
|
menu_none,
|
||||||
|
lora_Menu,
|
||||||
lora_picker,
|
lora_picker,
|
||||||
|
device_role_picker,
|
||||||
no_timeout_lora_picker,
|
no_timeout_lora_picker,
|
||||||
TZ_picker,
|
TZ_picker,
|
||||||
twelve_hour_picker,
|
twelve_hour_picker,
|
||||||
@@ -46,6 +48,7 @@ class menuHandler
|
|||||||
static void OnboardMessage();
|
static void OnboardMessage();
|
||||||
static void LoraRegionPicker(uint32_t duration = 30000);
|
static void LoraRegionPicker(uint32_t duration = 30000);
|
||||||
static void loraMenu();
|
static void loraMenu();
|
||||||
|
static void DeviceRolePicker();
|
||||||
static void handleMenuSwitch(OLEDDisplay *display);
|
static void handleMenuSwitch(OLEDDisplay *display);
|
||||||
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
|
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
|
||||||
static void clockMenu();
|
static void clockMenu();
|
||||||
|
|||||||
@@ -879,7 +879,26 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
config.display.heading_bold = false;
|
config.display.heading_bold = false;
|
||||||
|
|
||||||
const char *displayLine = ""; // Initialize to empty string by default
|
const char *displayLine = ""; // Initialize to empty string by default
|
||||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
|
|
||||||
|
bool usePhoneGPS = (ourNode && nodeDB->hasValidPosition(ourNode) &&
|
||||||
|
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED);
|
||||||
|
|
||||||
|
if (usePhoneGPS) {
|
||||||
|
// Phone-provided GPS is active
|
||||||
|
displayLine = "Phone GPS";
|
||||||
|
int yOffset = (isHighResolution) ? 3 : 1;
|
||||||
|
if (isHighResolution) {
|
||||||
|
NodeListRenderer::drawScaledXBitmap16x16(x, getTextPositions(display)[line] + yOffset - 5, imgSatellite_width,
|
||||||
|
imgSatellite_height, imgSatellite, display);
|
||||||
|
} else {
|
||||||
|
display->drawXbm(x + 1, getTextPositions(display)[line] + yOffset, imgSatellite_width, imgSatellite_height,
|
||||||
|
imgSatellite);
|
||||||
|
}
|
||||||
|
int xOffset = (isHighResolution) ? 6 : 0;
|
||||||
|
display->drawString(x + 11 + xOffset, getTextPositions(display)[line++], displayLine);
|
||||||
|
} else if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||||
|
// GPS disabled / not present
|
||||||
if (config.position.fixed_position) {
|
if (config.position.fixed_position) {
|
||||||
displayLine = "Fixed GPS";
|
displayLine = "Fixed GPS";
|
||||||
} else {
|
} else {
|
||||||
@@ -896,6 +915,7 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
int xOffset = (isHighResolution) ? 6 : 0;
|
int xOffset = (isHighResolution) ? 6 : 0;
|
||||||
display->drawString(x + 11 + xOffset, getTextPositions(display)[line++], displayLine);
|
display->drawString(x + 11 + xOffset, getTextPositions(display)[line++], displayLine);
|
||||||
} else {
|
} else {
|
||||||
|
// Onboard GPS
|
||||||
UIRenderer::drawGps(display, 0, getTextPositions(display)[line++], gpsStatus);
|
UIRenderer::drawGps(display, 0, getTextPositions(display)[line++], gpsStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,32 +942,61 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
|
|
||||||
// If GPS is off, no need to display these parts
|
// If GPS is off, no need to display these parts
|
||||||
if (strcmp(displayLine, "GPS off") != 0 && strcmp(displayLine, "No GPS") != 0) {
|
if (strcmp(displayLine, "GPS off") != 0 && strcmp(displayLine, "No GPS") != 0) {
|
||||||
|
// === Second Row: Last GPS Fix ===
|
||||||
|
if (gpsStatus->getLastFixMillis() > 0) {
|
||||||
|
uint32_t delta = (millis() - gpsStatus->getLastFixMillis()) / 1000; // seconds since last fix
|
||||||
|
uint32_t days = delta / 86400;
|
||||||
|
uint32_t hours = (delta % 86400) / 3600;
|
||||||
|
uint32_t mins = (delta % 3600) / 60;
|
||||||
|
uint32_t secs = delta % 60;
|
||||||
|
|
||||||
// === Second Row: Date ===
|
char buf[32];
|
||||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true);
|
#if defined(USE_EINK)
|
||||||
char datetimeStr[25];
|
// E-Ink: skip seconds, show only days/hours/mins
|
||||||
bool showTime = false; // set to true for full datetime
|
if (days > 0) {
|
||||||
UIRenderer::formatDateTime(datetimeStr, sizeof(datetimeStr), rtc_sec, display, showTime);
|
snprintf(buf, sizeof(buf), " Last: %ud %uh", days, hours);
|
||||||
char fullLine[40];
|
} else if (hours > 0) {
|
||||||
snprintf(fullLine, sizeof(fullLine), " Date: %s", datetimeStr);
|
snprintf(buf, sizeof(buf), " Last: %uh %um", hours, mins);
|
||||||
display->drawString(0, getTextPositions(display)[line++], fullLine);
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), " Last: %um", mins);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Non E-Ink: include seconds where useful
|
||||||
|
if (days > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "Last: %ud %uh", days, hours);
|
||||||
|
} else if (hours > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "Last: %uh %um", hours, mins);
|
||||||
|
} else if (mins > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "Last: %um %us", mins, secs);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), "Last: %us", secs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
display->drawString(0, getTextPositions(display)[line++], buf);
|
||||||
|
} else {
|
||||||
|
display->drawString(0, getTextPositions(display)[line++], "Last: ?");
|
||||||
|
}
|
||||||
|
|
||||||
// === Third Row: Latitude ===
|
// === Third Row: Latitude ===
|
||||||
char latStr[32];
|
char latStr[32];
|
||||||
snprintf(latStr, sizeof(latStr), " Lat: %.5f", geoCoord.getLatitude() * 1e-7);
|
snprintf(latStr, sizeof(latStr), "Lat: %.5f", geoCoord.getLatitude() * 1e-7);
|
||||||
display->drawString(x, getTextPositions(display)[line++], latStr);
|
display->drawString(x, getTextPositions(display)[line++], latStr);
|
||||||
|
|
||||||
// === Fourth Row: Longitude ===
|
// === Fourth Row: Longitude ===
|
||||||
char lonStr[32];
|
char lonStr[32];
|
||||||
snprintf(lonStr, sizeof(lonStr), " Lon: %.5f", geoCoord.getLongitude() * 1e-7);
|
snprintf(lonStr, sizeof(lonStr), "Lon: %.5f", geoCoord.getLongitude() * 1e-7);
|
||||||
display->drawString(x, getTextPositions(display)[line++], lonStr);
|
display->drawString(x, getTextPositions(display)[line++], lonStr);
|
||||||
|
|
||||||
// === Fifth Row: Altitude ===
|
// === Fifth Row: Altitude ===
|
||||||
char DisplayLineTwo[32] = {0};
|
char DisplayLineTwo[32] = {0};
|
||||||
|
int32_t alt = (strcmp(displayLine, "Phone GPS") == 0 && ourNode && nodeDB->hasValidPosition(ourNode))
|
||||||
|
? ourNode->position.altitude
|
||||||
|
: geoCoord.getAltitude();
|
||||||
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||||
snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), " Alt: %.0fft", geoCoord.getAltitude() * METERS_TO_FEET);
|
snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), "Alt: %.0fft", geoCoord.getAltitude() * METERS_TO_FEET);
|
||||||
} else {
|
} else {
|
||||||
snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), " Alt: %.0im", geoCoord.getAltitude());
|
snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), "Alt: %.0im", geoCoord.getAltitude());
|
||||||
}
|
}
|
||||||
display->drawString(x, getTextPositions(display)[line++], DisplayLineTwo);
|
display->drawString(x, getTextPositions(display)[line++], DisplayLineTwo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "NodeDB.h"
|
||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "graphics/emotes.h"
|
#include "graphics/emotes.h"
|
||||||
#include <OLEDDisplay.h>
|
#include <OLEDDisplay.h>
|
||||||
|
|||||||
@@ -288,5 +288,77 @@ const uint8_t digital_icon_clock[] PROGMEM = {0b00111100, 0b01000010, 0b10000101
|
|||||||
const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000,
|
const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000,
|
||||||
0b00100100, 0b01000010, 0b01000010, 0b11111111};
|
0b00100100, 0b01000010, 0b01000010, 0b11111111};
|
||||||
|
|
||||||
|
#define chirpy_width 38
|
||||||
|
#define chirpy_height 50
|
||||||
|
static unsigned char chirpy[] = {
|
||||||
|
0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01,
|
||||||
|
0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00,
|
||||||
|
0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f,
|
||||||
|
0xfe, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc,
|
||||||
|
0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0,
|
||||||
|
0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1,
|
||||||
|
0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0xcf, 0x7f, 0xfe, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0x81, 0xff,
|
||||||
|
0xff, 0x7f, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xc3, 0x00, 0xe0, 0x01, 0x00, 0xc3,
|
||||||
|
0x00, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0xc0, 0x30, 0x03, 0xe0, 0x01, 0xc0, 0x30, 0x03,
|
||||||
|
0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0,
|
||||||
|
0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xdf};
|
||||||
|
|
||||||
|
#define chirpy_width_hirez 76
|
||||||
|
#define chirpy_height_hirez 100
|
||||||
|
static unsigned char chirpy_hirez[] = {
|
||||||
|
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
|
||||||
|
0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc,
|
||||||
|
0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x03,
|
||||||
|
0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xf0, 0xff, 0x3f, 0xfc, 0xff, 0x00, 0xfc, 0x03, 0xf0,
|
||||||
|
0xff, 0xf0, 0xff, 0x3f, 0xfc, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f,
|
||||||
|
0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0,
|
||||||
|
0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff,
|
||||||
|
0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f,
|
||||||
|
0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0,
|
||||||
|
0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff,
|
||||||
|
0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00,
|
||||||
|
0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc,
|
||||||
|
0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03,
|
||||||
|
0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0,
|
||||||
|
0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f,
|
||||||
|
0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0,
|
||||||
|
0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x3f, 0xc0, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xf0, 0xff,
|
||||||
|
0x3f, 0xfc, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xf0, 0xff, 0x3f, 0xfc, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0x00, 0xfc, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
|
||||||
|
0xc0, 0x03, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0,
|
||||||
|
0x03, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00,
|
||||||
|
0x0f, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x0f,
|
||||||
|
0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0xc0, 0x03, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0xc0, 0x03, 0x3c,
|
||||||
|
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0xc0, 0x03, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0xc0, 0x03, 0x3c, 0x00,
|
||||||
|
0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0xf0, 0x00, 0x00,
|
||||||
|
0xfc, 0x03, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0xfc,
|
||||||
|
0x03, 0x00, 0xc0, 0x03, 0x3c, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x3c, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03,
|
||||||
|
0x00, 0xc0, 0x03, 0x3c, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x3c, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03, 0x00,
|
||||||
|
0xf0, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0xf0,
|
||||||
|
0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3};
|
||||||
|
|
||||||
|
#define chirpy_small_image_width 8
|
||||||
|
#define chirpy_small_image_height 8
|
||||||
|
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
|
||||||
|
|
||||||
#include "img/icon.xbm"
|
#include "img/icon.xbm"
|
||||||
static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning");
|
static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning");
|
||||||
+48
-48
@@ -41,78 +41,78 @@ void tftSetup(void)
|
|||||||
PacketAPI::create(PacketServer::init());
|
PacketAPI::create(PacketServer::init());
|
||||||
deviceScreen->init(new PacketClient);
|
deviceScreen->init(new PacketClient);
|
||||||
#else
|
#else
|
||||||
if (settingsMap[displayPanel] != no_screen) {
|
if (portduino_config.displayPanel != no_screen) {
|
||||||
DisplayDriverConfig displayConfig;
|
DisplayDriverConfig displayConfig;
|
||||||
static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S",
|
static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S",
|
||||||
"ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
|
"ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
|
||||||
static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"};
|
static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"};
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
if (settingsMap[displayPanel] == x11) {
|
if (portduino_config.displayPanel == x11) {
|
||||||
if (settingsMap[displayWidth] && settingsMap[displayHeight])
|
if (portduino_config.displayWidth && portduino_config.displayHeight)
|
||||||
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth],
|
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)portduino_config.displayWidth,
|
||||||
(uint16_t)settingsMap[displayHeight]);
|
(uint16_t)portduino_config.displayHeight);
|
||||||
else
|
else
|
||||||
displayConfig.device(DisplayDriverConfig::device_t::X11);
|
displayConfig.device(DisplayDriverConfig::device_t::X11);
|
||||||
} else
|
} else
|
||||||
#elif defined(USE_FRAMEBUFFER)
|
#elif defined(USE_FRAMEBUFFER)
|
||||||
if (settingsMap[displayPanel] == fb) {
|
if (portduino_config.displayPanel == fb) {
|
||||||
if (settingsMap[displayWidth] && settingsMap[displayHeight])
|
if (portduino_config.displayWidth && portduino_config.displayHeight)
|
||||||
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)settingsMap[displayWidth],
|
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)portduino_config.displayWidth,
|
||||||
(uint16_t)settingsMap[displayHeight]);
|
(uint16_t)portduino_config.displayHeight);
|
||||||
else
|
else
|
||||||
displayConfig.device(DisplayDriverConfig::device_t::FB);
|
displayConfig.device(DisplayDriverConfig::device_t::FB);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT)
|
displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT)
|
||||||
.panel(DisplayDriverConfig::panel_config_t{.type = panels[settingsMap[displayPanel]],
|
.panel(DisplayDriverConfig::panel_config_t{.type = panels[portduino_config.displayPanel],
|
||||||
.panel_width = (uint16_t)settingsMap[displayWidth],
|
.panel_width = (uint16_t)portduino_config.displayWidth,
|
||||||
.panel_height = (uint16_t)settingsMap[displayHeight],
|
.panel_height = (uint16_t)portduino_config.displayHeight,
|
||||||
.rotation = (bool)settingsMap[displayRotate],
|
.rotation = (bool)portduino_config.displayRotate,
|
||||||
.pin_cs = (int16_t)settingsMap[displayCS],
|
.pin_cs = (int16_t)portduino_config.displayCS.pin,
|
||||||
.pin_rst = (int16_t)settingsMap[displayReset],
|
.pin_rst = (int16_t)portduino_config.displayReset.pin,
|
||||||
.offset_x = (uint16_t)settingsMap[displayOffsetX],
|
.offset_x = (uint16_t)portduino_config.displayOffsetX,
|
||||||
.offset_y = (uint16_t)settingsMap[displayOffsetY],
|
.offset_y = (uint16_t)portduino_config.displayOffsetY,
|
||||||
.offset_rotation = (uint8_t)settingsMap[displayOffsetRotate],
|
.offset_rotation = (uint8_t)portduino_config.displayOffsetRotate,
|
||||||
.invert = settingsMap[displayInvert] ? true : false,
|
.invert = portduino_config.displayInvert ? true : false,
|
||||||
.rgb_order = (bool)settingsMap[displayRGBOrder],
|
.rgb_order = (bool)portduino_config.displayRGBOrder,
|
||||||
.dlen_16bit = settingsMap[displayPanel] == ili9486 ||
|
.dlen_16bit = portduino_config.displayPanel == ili9486 ||
|
||||||
settingsMap[displayPanel] == ili9488})
|
portduino_config.displayPanel == ili9488})
|
||||||
.bus(DisplayDriverConfig::bus_config_t{.freq_write = (uint32_t)settingsMap[displayBusFrequency],
|
.bus(DisplayDriverConfig::bus_config_t{.freq_write = (uint32_t)portduino_config.displayBusFrequency,
|
||||||
.freq_read = 16000000,
|
.freq_read = 16000000,
|
||||||
.spi{.pin_dc = (int8_t)settingsMap[displayDC],
|
.spi{.pin_dc = (int8_t)portduino_config.displayDC.pin,
|
||||||
.use_lock = true,
|
.use_lock = true,
|
||||||
.spi_host = (uint16_t)settingsMap[displayspidev]}})
|
.spi_host = (uint16_t)portduino_config.display_spi_dev_int}})
|
||||||
.input(DisplayDriverConfig::input_config_t{.keyboardDevice = settingsStrings[keyboardDevice],
|
.input(DisplayDriverConfig::input_config_t{.keyboardDevice = portduino_config.keyboardDevice,
|
||||||
.pointerDevice = settingsStrings[pointerDevice]})
|
.pointerDevice = portduino_config.pointerDevice})
|
||||||
.light(DisplayDriverConfig::light_config_t{.pin_bl = (int16_t)settingsMap[displayBacklight],
|
.light(DisplayDriverConfig::light_config_t{.pin_bl = (int16_t)portduino_config.displayBacklight.pin,
|
||||||
.pwm_channel = (int8_t)settingsMap[displayBacklightPWMChannel],
|
.pwm_channel = (int8_t)portduino_config.displayBacklightPWMChannel.pin,
|
||||||
.invert = (bool)settingsMap[displayBacklightInvert]});
|
.invert = (bool)portduino_config.displayBacklightInvert});
|
||||||
if (settingsMap[touchscreenI2CAddr] == -1) {
|
if (portduino_config.touchscreenI2CAddr == -1) {
|
||||||
displayConfig.touch(
|
displayConfig.touch(
|
||||||
DisplayDriverConfig::touch_config_t{.type = touch[settingsMap[touchscreenModule]],
|
DisplayDriverConfig::touch_config_t{.type = touch[portduino_config.touchscreenModule],
|
||||||
.freq = (uint32_t)settingsMap[touchscreenBusFrequency],
|
.freq = (uint32_t)portduino_config.touchscreenBusFrequency,
|
||||||
.pin_int = (int16_t)settingsMap[touchscreenIRQ],
|
.pin_int = (int16_t)portduino_config.touchscreenIRQ.pin,
|
||||||
.offset_rotation = (uint8_t)settingsMap[touchscreenRotate],
|
.offset_rotation = (uint8_t)portduino_config.touchscreenRotate,
|
||||||
.spi{
|
.spi{
|
||||||
.spi_host = (int8_t)settingsMap[touchscreenspidev],
|
.spi_host = (int8_t)portduino_config.touchscreen_spi_dev_int,
|
||||||
},
|
},
|
||||||
.pin_cs = (int16_t)settingsMap[touchscreenCS]});
|
.pin_cs = (int16_t)portduino_config.touchscreenCS.pin});
|
||||||
} else {
|
} else {
|
||||||
displayConfig.touch(DisplayDriverConfig::touch_config_t{
|
displayConfig.touch(DisplayDriverConfig::touch_config_t{
|
||||||
.type = touch[settingsMap[touchscreenModule]],
|
.type = touch[portduino_config.touchscreenModule],
|
||||||
.freq = (uint32_t)settingsMap[touchscreenBusFrequency],
|
.freq = (uint32_t)portduino_config.touchscreenBusFrequency,
|
||||||
.x_min = 0,
|
.x_min = 0,
|
||||||
.x_max =
|
.x_max = (int16_t)((portduino_config.touchscreenRotate & 1 ? portduino_config.displayWidth
|
||||||
(int16_t)((settingsMap[touchscreenRotate] & 1 ? settingsMap[displayWidth] : settingsMap[displayHeight]) -
|
: portduino_config.displayHeight) -
|
||||||
1),
|
1),
|
||||||
.y_min = 0,
|
.y_min = 0,
|
||||||
.y_max =
|
.y_max = (int16_t)((portduino_config.touchscreenRotate & 1 ? portduino_config.displayHeight
|
||||||
(int16_t)((settingsMap[touchscreenRotate] & 1 ? settingsMap[displayHeight] : settingsMap[displayWidth]) -
|
: portduino_config.displayWidth) -
|
||||||
1),
|
1),
|
||||||
.pin_int = (int16_t)settingsMap[touchscreenIRQ],
|
.pin_int = (int16_t)portduino_config.touchscreenIRQ.pin,
|
||||||
.offset_rotation = (uint8_t)settingsMap[touchscreenRotate],
|
.offset_rotation = (uint8_t)portduino_config.touchscreenRotate,
|
||||||
.i2c{.i2c_addr = (uint8_t)settingsMap[touchscreenI2CAddr]}});
|
.i2c{.i2c_addr = (uint8_t)portduino_config.touchscreenI2CAddr}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deviceScreen = &DeviceScreen::create(&displayConfig);
|
deviceScreen = &DeviceScreen::create(&displayConfig);
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ int32_t LinuxInput::runOnce()
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
if (settingsStrings[keyboardDevice] == "")
|
if (portduino_config.keyboardDevice == "")
|
||||||
return disable();
|
return disable();
|
||||||
fd = open(settingsStrings[keyboardDevice].c_str(), O_RDWR);
|
fd = open(portduino_config.keyboardDevice.c_str(), O_RDWR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return disable();
|
return disable();
|
||||||
ret = ioctl(fd, EVIOCGRAB, (void *)1);
|
ret = ioctl(fd, EVIOCGRAB, (void *)1);
|
||||||
|
|||||||
@@ -40,10 +40,7 @@ bool RotaryEncoderImpl::init()
|
|||||||
|
|
||||||
int32_t RotaryEncoderImpl::runOnce()
|
int32_t RotaryEncoderImpl::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e{originName, INPUT_BROKER_NONE, 0, 0, 0};
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
|
||||||
e.source = this->originName;
|
|
||||||
|
|
||||||
static uint32_t lastPressed = millis();
|
static uint32_t lastPressed = millis();
|
||||||
if (rotary->readButton() == RotaryEncoder::ButtonState::BUTTON_PRESSED) {
|
if (rotary->readButton() == RotaryEncoder::ButtonState::BUTTON_PRESSED) {
|
||||||
if (lastPressed + 200 < millis()) {
|
if (lastPressed + 200 < millis()) {
|
||||||
@@ -70,7 +67,7 @@ int32_t RotaryEncoderImpl::runOnce()
|
|||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 20;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -18,7 +18,7 @@ TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTo
|
|||||||
void TouchScreenImpl1::init()
|
void TouchScreenImpl1::init()
|
||||||
{
|
{
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[touchscreenModule]) {
|
if (portduino_config.touchscreenModule) {
|
||||||
TouchScreenBase::init(true);
|
TouchScreenBase::init(true);
|
||||||
inputBroker->registerSource(this);
|
inputBroker->registerSource(this);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#ifndef TB_DIRECTION
|
#ifndef TB_DIRECTION
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
#include "PortduinoGlue.h"
|
#include "PortduinoGlue.h"
|
||||||
#define TB_DIRECTION (PinStatus) settingsMap[tbDirection]
|
#define TB_DIRECTION (PinStatus) portduino_config.lora_usb_vid
|
||||||
#else
|
#else
|
||||||
#define TB_DIRECTION RISING
|
#define TB_DIRECTION RISING
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ void CardKbI2cImpl::init()
|
|||||||
if (cardkb_found.address == 0x00) {
|
if (cardkb_found.address == 0x00) {
|
||||||
LOG_DEBUG("Rescan for I2C keyboard");
|
LOG_DEBUG("Rescan for I2C keyboard");
|
||||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR, TCA8418_KB_ADDR};
|
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR, TCA8418_KB_ADDR};
|
||||||
|
#if defined(T_LORA_PAGER)
|
||||||
uint8_t i2caddr_asize = sizeof(i2caddr_scan) / sizeof(i2caddr_scan[0]);
|
uint8_t i2caddr_asize = sizeof(i2caddr_scan) / sizeof(i2caddr_scan[0]);
|
||||||
|
#else
|
||||||
|
uint8_t i2caddr_asize = 5;
|
||||||
|
#endif
|
||||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||||
|
|
||||||
#if WIRE_INTERFACES_COUNT == 2
|
#if WIRE_INTERFACES_COUNT == 2
|
||||||
|
|||||||
+54
-55
@@ -390,7 +390,7 @@ void setup()
|
|||||||
|
|
||||||
concurrency::hasBeenSetup = true;
|
concurrency::hasBeenSetup = true;
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
SPISettings spiSettings(settingsMap[spiSpeed], MSBFIRST, SPI_MODE0);
|
SPISettings spiSettings(portduino_config.spiSpeed, MSBFIRST, SPI_MODE0);
|
||||||
#else
|
#else
|
||||||
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
||||||
#endif
|
#endif
|
||||||
@@ -535,9 +535,9 @@ void setup()
|
|||||||
#elif defined(I2C_SDA) && !defined(ARCH_RP2040)
|
#elif defined(I2C_SDA) && !defined(ARCH_RP2040)
|
||||||
Wire.begin(I2C_SDA, I2C_SCL);
|
Wire.begin(I2C_SDA, I2C_SCL);
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
if (settingsStrings[i2cdev] != "") {
|
if (portduino_config.i2cdev != "") {
|
||||||
LOG_INFO("Use %s as I2C device", settingsStrings[i2cdev].c_str());
|
LOG_INFO("Use %s as I2C device", portduino_config.i2cdev.c_str());
|
||||||
Wire.begin(settingsStrings[i2cdev].c_str());
|
Wire.begin(portduino_config.i2cdev.c_str());
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("No I2C device configured, Skip");
|
LOG_INFO("No I2C device configured, Skip");
|
||||||
}
|
}
|
||||||
@@ -583,7 +583,7 @@ void setup()
|
|||||||
#if defined(I2C_SDA)
|
#if defined(I2C_SDA)
|
||||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
if (settingsStrings[i2cdev] != "") {
|
if (portduino_config.i2cdev != "") {
|
||||||
LOG_INFO("Scan for i2c devices");
|
LOG_INFO("Scan for i2c devices");
|
||||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||||
}
|
}
|
||||||
@@ -743,6 +743,7 @@ void setup()
|
|||||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RAK12035, meshtastic_TelemetrySensorType_RAK12035);
|
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RAK12035, meshtastic_TelemetrySensorType_RAK12035);
|
||||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075);
|
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075);
|
||||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SCD4X, meshtastic_TelemetrySensorType_SCD4X);
|
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SCD4X, meshtastic_TelemetrySensorType_SCD4X);
|
||||||
|
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::TSL2561, meshtastic_TelemetrySensorType_TSL2561);
|
||||||
|
|
||||||
i2cScanner.reset();
|
i2cScanner.reset();
|
||||||
#endif
|
#endif
|
||||||
@@ -855,7 +856,7 @@ void setup()
|
|||||||
SPI.begin(false);
|
SPI.begin(false);
|
||||||
#endif // HW_SPI1_DEVICE
|
#endif // HW_SPI1_DEVICE
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
if (settingsStrings[spidev] != "ch341") {
|
if (portduino_config.lora_spi_dev != "ch341") {
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
}
|
}
|
||||||
#elif !defined(ARCH_ESP32) // ARCH_RP2040
|
#elif !defined(ARCH_ESP32) // ARCH_RP2040
|
||||||
@@ -881,7 +882,7 @@ void setup()
|
|||||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS)
|
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS)
|
||||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) &&
|
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) &&
|
||||||
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||||
}
|
}
|
||||||
@@ -982,13 +983,13 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_PORTDUINO)
|
#if defined(ARCH_PORTDUINO)
|
||||||
|
|
||||||
if (settingsMap.count(userButtonPin) != 0 && settingsMap[userButtonPin] != RADIOLIB_NC) {
|
if (portduino_config.userButtonPin.enabled) {
|
||||||
|
|
||||||
LOG_DEBUG("Use GPIO%02d for button", settingsMap[userButtonPin]);
|
LOG_DEBUG("Use GPIO%02d for button", portduino_config.userButtonPin.pin);
|
||||||
UserButtonThread = new ButtonThread("UserButton");
|
UserButtonThread = new ButtonThread("UserButton");
|
||||||
if (screen) {
|
if (screen) {
|
||||||
ButtonConfig config;
|
ButtonConfig config;
|
||||||
config.pinNumber = (uint8_t)settingsMap[userButtonPin];
|
config.pinNumber = (uint8_t)portduino_config.userButtonPin.pin;
|
||||||
config.activeLow = true;
|
config.activeLow = true;
|
||||||
config.activePullup = true;
|
config.activePullup = true;
|
||||||
config.pullupSense = INPUT_PULLUP;
|
config.pullupSense = INPUT_PULLUP;
|
||||||
@@ -1145,7 +1146,7 @@ void setup()
|
|||||||
if (screen)
|
if (screen)
|
||||||
screen->setup();
|
screen->setup();
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) &&
|
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) &&
|
||||||
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||||
screen->setup();
|
screen->setup();
|
||||||
}
|
}
|
||||||
@@ -1161,15 +1162,10 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
const struct {
|
|
||||||
configNames cfgName;
|
|
||||||
std::string strName;
|
|
||||||
} loraModules[] = {{use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"}, {use_sx1280, "sx1280"},
|
|
||||||
{use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
|
||||||
// as one can't use a function pointer to the class constructor:
|
// as one can't use a function pointer to the class constructor:
|
||||||
auto loraModuleInterface = [](configNames cfgName, LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
|
auto loraModuleInterface = [](LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||||
RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) {
|
RADIOLIB_PIN_TYPE busy) {
|
||||||
switch (cfgName) {
|
switch (portduino_config.lora_module) {
|
||||||
case use_rf95:
|
case use_rf95:
|
||||||
return (RadioInterface *)new RF95Interface(hal, cs, irq, rst, busy);
|
return (RadioInterface *)new RF95Interface(hal, cs, irq, rst, busy);
|
||||||
case use_sx1262:
|
case use_sx1262:
|
||||||
@@ -1186,31 +1182,34 @@ void setup()
|
|||||||
return (RadioInterface *)new LR1121Interface(hal, cs, irq, rst, busy);
|
return (RadioInterface *)new LR1121Interface(hal, cs, irq, rst, busy);
|
||||||
case use_llcc68:
|
case use_llcc68:
|
||||||
return (RadioInterface *)new LLCC68Interface(hal, cs, irq, rst, busy);
|
return (RadioInterface *)new LLCC68Interface(hal, cs, irq, rst, busy);
|
||||||
|
case use_simradio:
|
||||||
|
return (RadioInterface *)new SimRadio;
|
||||||
default:
|
default:
|
||||||
assert(0); // shouldn't happen
|
assert(0); // shouldn't happen
|
||||||
return (RadioInterface *)nullptr;
|
return (RadioInterface *)nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (auto &loraModule : loraModules) {
|
|
||||||
if (settingsMap[loraModule.cfgName] && !rIf) {
|
LOG_DEBUG("Activate %s radio on SPI port %s", portduino_config.loraModules[portduino_config.lora_module].c_str(),
|
||||||
LOG_DEBUG("Activate %s radio on SPI port %s", loraModule.strName.c_str(), settingsStrings[spidev].c_str());
|
portduino_config.lora_spi_dev.c_str());
|
||||||
if (settingsStrings[spidev] == "ch341") {
|
if (portduino_config.lora_spi_dev == "ch341") {
|
||||||
RadioLibHAL = ch341Hal;
|
RadioLibHAL = ch341Hal;
|
||||||
} else {
|
} else {
|
||||||
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||||
}
|
|
||||||
rIf = loraModuleInterface(loraModule.cfgName, (LockingArduinoHal *)RadioLibHAL, settingsMap[cs_pin],
|
|
||||||
settingsMap[irq_pin], settingsMap[reset_pin], settingsMap[busy_pin]);
|
|
||||||
if (!rIf->init()) {
|
|
||||||
LOG_WARN("No %s radio", loraModule.strName.c_str());
|
|
||||||
delete rIf;
|
|
||||||
rIf = NULL;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else {
|
|
||||||
LOG_INFO("%s init success", loraModule.strName.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
rIf =
|
||||||
|
loraModuleInterface((LockingArduinoHal *)RadioLibHAL, portduino_config.lora_cs_pin.pin, portduino_config.lora_irq_pin.pin,
|
||||||
|
portduino_config.lora_reset_pin.pin, portduino_config.lora_busy_pin.pin);
|
||||||
|
|
||||||
|
if (!rIf->init()) {
|
||||||
|
LOG_WARN("No %s radio", portduino_config.loraModules[portduino_config.lora_module].c_str());
|
||||||
|
delete rIf;
|
||||||
|
rIf = NULL;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
LOG_INFO("%s init success", portduino_config.loraModules[portduino_config.lora_module].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(HW_SPI1_DEVICE)
|
#elif defined(HW_SPI1_DEVICE)
|
||||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings);
|
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings);
|
||||||
#else // HW_SPI1_DEVICE
|
#else // HW_SPI1_DEVICE
|
||||||
@@ -1232,20 +1231,6 @@ void setup()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_PORTDUINO)
|
|
||||||
if (!rIf) {
|
|
||||||
rIf = new SimRadio;
|
|
||||||
if (!rIf->init()) {
|
|
||||||
LOG_WARN("No simulated radio");
|
|
||||||
delete rIf;
|
|
||||||
rIf = NULL;
|
|
||||||
} else {
|
|
||||||
LOG_INFO("Use SIMULATED radio!");
|
|
||||||
radioType = SIM_RADIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RF95_IRQ) && RADIOLIB_EXCLUDE_SX127X != 1
|
#if defined(RF95_IRQ) && RADIOLIB_EXCLUDE_SX127X != 1
|
||||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||||
rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
|
rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
|
||||||
@@ -1460,7 +1445,7 @@ void setup()
|
|||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
#if __has_include(<ulfius.h>)
|
#if __has_include(<ulfius.h>)
|
||||||
if (settingsMap[webserverport] != -1) {
|
if (portduino_config.webserverport != -1) {
|
||||||
piwebServerThread = new PiWebServerThread();
|
piwebServerThread = new PiWebServerThread();
|
||||||
std::atexit([] { delete piwebServerThread; });
|
std::atexit([] { delete piwebServerThread; });
|
||||||
}
|
}
|
||||||
@@ -1521,6 +1506,9 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
|||||||
deviceMetadata.hw_model = HW_VENDOR;
|
deviceMetadata.hw_model = HW_VENDOR;
|
||||||
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
|
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
|
||||||
deviceMetadata.excluded_modules = meshtastic_ExcludedModules_EXCLUDED_NONE;
|
deviceMetadata.excluded_modules = meshtastic_ExcludedModules_EXCLUDED_NONE;
|
||||||
|
#if MESHTASTIC_EXCLUDE_MQTT
|
||||||
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_MQTT_CONFIG;
|
||||||
|
#endif
|
||||||
#if MESHTASTIC_EXCLUDE_REMOTEHARDWARE
|
#if MESHTASTIC_EXCLUDE_REMOTEHARDWARE
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_REMOTEHARDWARE_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_REMOTEHARDWARE_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
@@ -1543,10 +1531,21 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
|||||||
#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL
|
#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
#ifndef ARCH_ESP32
|
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
|
// PAXCOUNTER is only supported on ESP32 due to memory constraints
|
||||||
|
#else
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_PAXCOUNTER_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_PAXCOUNTER_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(HAS_RGB_LED) && !RAK_4631
|
#if MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||||
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_STOREFORWARD_CONFIG;
|
||||||
|
#endif
|
||||||
|
#if MESHTASTIC_EXCLUDE_RANGETEST
|
||||||
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_RANGETEST_CONFIG;
|
||||||
|
#endif
|
||||||
|
#if MESHTASTIC_EXCLUDE_NEIGHBORINFO
|
||||||
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_NEIGHBORINFO_CONFIG;
|
||||||
|
#endif
|
||||||
|
#if (!defined(HAS_RGB_LED) && !defined(RAK_4631)) || defined(MESHTASTIC_EXCLUDE_AMBIENTLIGHTING)
|
||||||
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG;
|
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
|
|||||||
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
||||||
// specified (may be dangerous if using external PA and LR11x0 power config forgotten)
|
// specified (may be dangerous if using external PA and LR11x0 power config forgotten)
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
#define LR1110_MAX_POWER settingsMap[lr1110_max_power]
|
#define LR1110_MAX_POWER portduino_config.lr1110_max_power
|
||||||
#endif
|
#endif
|
||||||
#ifndef LR1110_MAX_POWER
|
#ifndef LR1110_MAX_POWER
|
||||||
#define LR1110_MAX_POWER 22
|
#define LR1110_MAX_POWER 22
|
||||||
@@ -30,7 +30,7 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
|
|||||||
// the 2.4G part maxes at 13dBm
|
// the 2.4G part maxes at 13dBm
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
#define LR1120_MAX_POWER settingsMap[lr1120_max_power]
|
#define LR1120_MAX_POWER portduino_config.lr1120_max_power
|
||||||
#endif
|
#endif
|
||||||
#ifndef LR1120_MAX_POWER
|
#ifndef LR1120_MAX_POWER
|
||||||
#define LR1120_MAX_POWER 13
|
#define LR1120_MAX_POWER 13
|
||||||
@@ -55,7 +55,7 @@ template <typename T> bool LR11x0Interface<T>::init()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
|
float tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000;
|
||||||
// FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE
|
// FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE
|
||||||
#elif !defined(LR11X0_DIO3_TCXO_VOLTAGE)
|
#elif !defined(LR11X0_DIO3_TCXO_VOLTAGE)
|
||||||
float tcxoVoltage =
|
float tcxoVoltage =
|
||||||
|
|||||||
@@ -34,8 +34,11 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
|||||||
bool weWereNextHop = false;
|
bool weWereNextHop = false;
|
||||||
if (wasSeenRecently(p, true, &wasFallback, &weWereNextHop)) { // Note: this will also add a recent packet record
|
if (wasSeenRecently(p, true, &wasFallback, &weWereNextHop)) { // Note: this will also add a recent packet record
|
||||||
printPacket("Ignore dupe incoming msg", p);
|
printPacket("Ignore dupe incoming msg", p);
|
||||||
rxDupe++;
|
|
||||||
stopRetransmission(p->from, p->id);
|
if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA) {
|
||||||
|
rxDupe++;
|
||||||
|
stopRetransmission(p->from, p->id);
|
||||||
|
}
|
||||||
|
|
||||||
// If it was a fallback to flooding, try to relay again
|
// If it was a fallback to flooding, try to relay again
|
||||||
if (wasFallback) {
|
if (wasFallback) {
|
||||||
@@ -71,10 +74,11 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
|
|||||||
if (p->from != 0) {
|
if (p->from != 0) {
|
||||||
meshtastic_NodeInfoLite *origTx = nodeDB->getMeshNode(p->from);
|
meshtastic_NodeInfoLite *origTx = nodeDB->getMeshNode(p->from);
|
||||||
if (origTx) {
|
if (origTx) {
|
||||||
// Either relayer of ACK was also a relayer of the packet, or we were the relayer and the ACK came directly from
|
// Either relayer of ACK was also a relayer of the packet, or we were the *only* relayer and the ACK came directly
|
||||||
// the destination
|
// from the destination
|
||||||
if (wasRelayer(p->relay_node, p->decoded.request_id, p->to) ||
|
if (wasRelayer(p->relay_node, p->decoded.request_id, p->to) ||
|
||||||
(wasRelayer(ourRelayID, p->decoded.request_id, p->to) && p->hop_start != 0 && p->hop_start == p->hop_limit)) {
|
(p->hop_start != 0 && p->hop_start == p->hop_limit &&
|
||||||
|
wasSoleRelayer(ourRelayID, p->decoded.request_id, p->to))) {
|
||||||
if (origTx->next_hop != p->relay_node) { // Not already set
|
if (origTx->next_hop != p->relay_node) { // Not already set
|
||||||
LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply", p->from, p->relay_node);
|
LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply", p->from, p->relay_node);
|
||||||
origTx->next_hop = p->relay_node;
|
origTx->next_hop = p->relay_node;
|
||||||
|
|||||||
+23
-3
@@ -673,7 +673,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
#endif
|
#endif
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
bool hasScreen = false;
|
bool hasScreen = false;
|
||||||
if (settingsMap[displayPanel])
|
if (portduino_config.displayPanel)
|
||||||
hasScreen = true;
|
hasScreen = true;
|
||||||
else
|
else
|
||||||
hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
|
hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
|
||||||
@@ -775,7 +775,9 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
|
|
||||||
moduleConfig.version = DEVICESTATE_CUR_VER;
|
moduleConfig.version = DEVICESTATE_CUR_VER;
|
||||||
moduleConfig.has_mqtt = true;
|
moduleConfig.has_mqtt = true;
|
||||||
|
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
||||||
moduleConfig.has_range_test = true;
|
moduleConfig.has_range_test = true;
|
||||||
|
#endif
|
||||||
moduleConfig.has_serial = true;
|
moduleConfig.has_serial = true;
|
||||||
moduleConfig.has_store_forward = true;
|
moduleConfig.has_store_forward = true;
|
||||||
moduleConfig.has_telemetry = true;
|
moduleConfig.has_telemetry = true;
|
||||||
@@ -841,6 +843,12 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.canned_message.inputbroker_event_press = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
moduleConfig.canned_message.inputbroker_event_press = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
#endif
|
#endif
|
||||||
moduleConfig.has_canned_message = true;
|
moduleConfig.has_canned_message = true;
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AUDIO
|
||||||
|
moduleConfig.has_audio = true;
|
||||||
|
#endif
|
||||||
|
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
|
moduleConfig.has_paxcounter = true;
|
||||||
|
#endif
|
||||||
#if USERPREFS_MQTT_ENABLED && !MESHTASTIC_EXCLUDE_MQTT
|
#if USERPREFS_MQTT_ENABLED && !MESHTASTIC_EXCLUDE_MQTT
|
||||||
moduleConfig.mqtt.enabled = true;
|
moduleConfig.mqtt.enabled = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -883,12 +891,14 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.detection_sensor.detection_trigger_type = meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH;
|
moduleConfig.detection_sensor.detection_trigger_type = meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH;
|
||||||
moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
|
moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
||||||
moduleConfig.has_ambient_lighting = true;
|
moduleConfig.has_ambient_lighting = true;
|
||||||
moduleConfig.ambient_lighting.current = 10;
|
moduleConfig.ambient_lighting.current = 10;
|
||||||
// Default to a color based on our node number
|
// Default to a color based on our node number
|
||||||
moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
|
moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
|
||||||
moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
||||||
moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
||||||
|
#endif
|
||||||
|
|
||||||
initModuleConfigIntervals();
|
initModuleConfigIntervals();
|
||||||
}
|
}
|
||||||
@@ -1334,8 +1344,8 @@ void NodeDB::loadFromDisk()
|
|||||||
}
|
}
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
// set any config overrides
|
// set any config overrides
|
||||||
if (settingsMap[has_configDisplayMode]) {
|
if (portduino_config.has_configDisplayMode) {
|
||||||
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)settingsMap[configDisplayMode];
|
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)portduino_config.configDisplayMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1428,15 +1438,25 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
|||||||
moduleConfig.has_canned_message = true;
|
moduleConfig.has_canned_message = true;
|
||||||
moduleConfig.has_external_notification = true;
|
moduleConfig.has_external_notification = true;
|
||||||
moduleConfig.has_mqtt = true;
|
moduleConfig.has_mqtt = true;
|
||||||
|
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
||||||
moduleConfig.has_range_test = true;
|
moduleConfig.has_range_test = true;
|
||||||
|
#endif
|
||||||
moduleConfig.has_serial = true;
|
moduleConfig.has_serial = true;
|
||||||
|
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||||
moduleConfig.has_store_forward = true;
|
moduleConfig.has_store_forward = true;
|
||||||
|
#endif
|
||||||
moduleConfig.has_telemetry = true;
|
moduleConfig.has_telemetry = true;
|
||||||
moduleConfig.has_neighbor_info = true;
|
moduleConfig.has_neighbor_info = true;
|
||||||
moduleConfig.has_detection_sensor = true;
|
moduleConfig.has_detection_sensor = true;
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
||||||
moduleConfig.has_ambient_lighting = true;
|
moduleConfig.has_ambient_lighting = true;
|
||||||
|
#endif
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AUDIO
|
||||||
moduleConfig.has_audio = true;
|
moduleConfig.has_audio = true;
|
||||||
|
#endif
|
||||||
|
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
moduleConfig.has_paxcounter = true;
|
moduleConfig.has_paxcounter = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
success &=
|
success &=
|
||||||
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||||
|
|||||||
+25
-10
@@ -294,7 +294,7 @@ void PacketHistory::insert(const PacketRecord &r)
|
|||||||
|
|
||||||
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
||||||
* @return true if node was indeed a relayer, false if not */
|
* @return true if node was indeed a relayer, false if not */
|
||||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
|
bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender, bool *wasSole)
|
||||||
{
|
{
|
||||||
if (!initOk()) {
|
if (!initOk()) {
|
||||||
LOG_ERROR("PacketHistory - wasRelayer: NOT INITIALIZED!");
|
LOG_ERROR("PacketHistory - wasRelayer: NOT INITIALIZED!");
|
||||||
@@ -322,27 +322,42 @@ bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const N
|
|||||||
found->sender, found->id, found->next_hop, millis() - found->rxTimeMsec, found->relayed_by[0], found->relayed_by[1],
|
found->sender, found->id, found->next_hop, millis() - found->rxTimeMsec, found->relayed_by[0], found->relayed_by[1],
|
||||||
found->relayed_by[2], relayer);
|
found->relayed_by[2], relayer);
|
||||||
#endif
|
#endif
|
||||||
return wasRelayer(relayer, *found);
|
return wasRelayer(relayer, *found, wasSole);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||||
* @return true if node was indeed a relayer, false if not */
|
* @return true if node was indeed a relayer, false if not */
|
||||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const PacketRecord &r)
|
bool PacketHistory::wasRelayer(const uint8_t relayer, const PacketRecord &r, bool *wasSole)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < NUM_RELAYERS; i++) {
|
bool found = false;
|
||||||
|
bool other_present = false;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < NUM_RELAYERS; ++i) {
|
||||||
if (r.relayed_by[i] == relayer) {
|
if (r.relayed_by[i] == relayer) {
|
||||||
#if VERBOSE_PACKET_HISTORY
|
found = true;
|
||||||
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? YES", r.sender, r.id,
|
} else if (r.relayed_by[i] != 0) {
|
||||||
r.relayed_by[0], r.relayed_by[1], r.relayed_by[2], relayer);
|
other_present = true;
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wasSole) {
|
||||||
|
*wasSole = (found && !other_present);
|
||||||
|
}
|
||||||
|
|
||||||
#if VERBOSE_PACKET_HISTORY
|
#if VERBOSE_PACKET_HISTORY
|
||||||
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? NO", r.sender, r.id, r.relayed_by[0],
|
LOG_DEBUG("Packet History - was rel.PR.: s=%08x id=%08x rls=%02x %02x %02x / rl=%02x? NO", r.sender, r.id, r.relayed_by[0],
|
||||||
r.relayed_by[1], r.relayed_by[2], relayer);
|
r.relayed_by[1], r.relayed_by[2], relayer);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a certain node was the *only* relayer of a packet in the history given an ID and sender
|
||||||
|
bool PacketHistory::wasSoleRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
|
||||||
|
{
|
||||||
|
bool wasSole = false;
|
||||||
|
wasRelayer(relayer, id, sender, &wasSole);
|
||||||
|
return wasSole;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ class PacketHistory
|
|||||||
void insert(const PacketRecord &r); // Insert or replace a packet record in the history
|
void insert(const PacketRecord &r); // Insert or replace a packet record in the history
|
||||||
|
|
||||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||||
|
* If wasSole is not nullptr, it will be set to true if the relayer was the only relayer of that packet
|
||||||
* @return true if node was indeed a relayer, false if not */
|
* @return true if node was indeed a relayer, false if not */
|
||||||
bool wasRelayer(const uint8_t relayer, const PacketRecord &r);
|
bool wasRelayer(const uint8_t relayer, const PacketRecord &r, bool *wasSole = nullptr);
|
||||||
|
|
||||||
PacketHistory(const PacketHistory &); // non construction-copyable
|
PacketHistory(const PacketHistory &); // non construction-copyable
|
||||||
PacketHistory &operator=(const PacketHistory &); // non copyable
|
PacketHistory &operator=(const PacketHistory &); // non copyable
|
||||||
@@ -54,8 +55,12 @@ class PacketHistory
|
|||||||
bool *weWereNextHop = nullptr);
|
bool *weWereNextHop = nullptr);
|
||||||
|
|
||||||
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
/* Check if a certain node was a relayer of a packet in the history given an ID and sender
|
||||||
|
* If wasSole is not nullptr, it will be set to true if the relayer was the only relayer of that packet
|
||||||
* @return true if node was indeed a relayer, false if not */
|
* @return true if node was indeed a relayer, false if not */
|
||||||
bool wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
bool wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender, bool *wasSole = nullptr);
|
||||||
|
|
||||||
|
// Check if a certain node was the *only* relayer of a packet in the history given an ID and sender
|
||||||
|
bool wasSoleRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||||
|
|
||||||
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
// Remove a relayer from the list of relayers of a packet in the history given an ID and sender
|
||||||
void removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
void removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender);
|
||||||
|
|||||||
@@ -34,6 +34,21 @@
|
|||||||
// Flag to indicate a heartbeat was received and we should send queue status
|
// Flag to indicate a heartbeat was received and we should send queue status
|
||||||
bool heartbeatReceived = false;
|
bool heartbeatReceived = false;
|
||||||
|
|
||||||
|
// Helper function to skip excluded module configs and advance state
|
||||||
|
size_t PhoneAPI::skipExcludedModuleConfig(uint8_t *buf)
|
||||||
|
{
|
||||||
|
config_state++;
|
||||||
|
if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) {
|
||||||
|
if (config_nonce == SPECIAL_NONCE_ONLY_CONFIG) {
|
||||||
|
state = STATE_SEND_FILEMANIFEST;
|
||||||
|
} else {
|
||||||
|
state = STATE_SEND_OTHER_NODEINFOS;
|
||||||
|
}
|
||||||
|
config_state = 0;
|
||||||
|
}
|
||||||
|
return getFromRadio(buf);
|
||||||
|
}
|
||||||
|
|
||||||
PhoneAPI::PhoneAPI()
|
PhoneAPI::PhoneAPI()
|
||||||
{
|
{
|
||||||
lastContactMsec = millis();
|
lastContactMsec = millis();
|
||||||
@@ -354,20 +369,35 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
|
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_external_notification_tag:
|
case meshtastic_ModuleConfig_external_notification_tag:
|
||||||
|
#if !(NO_EXT_GPIO || MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION)
|
||||||
LOG_DEBUG("Send module config: ext notification");
|
LOG_DEBUG("Send module config: ext notification");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
|
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("External Notification module excluded from build, skipping");
|
||||||
|
return skipExcludedModuleConfig(buf);
|
||||||
|
#endif
|
||||||
case meshtastic_ModuleConfig_store_forward_tag:
|
case meshtastic_ModuleConfig_store_forward_tag:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||||
LOG_DEBUG("Send module config: store forward");
|
LOG_DEBUG("Send module config: store forward");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.store_forward = moduleConfig.store_forward;
|
fromRadioScratch.moduleConfig.payload_variant.store_forward = moduleConfig.store_forward;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Store & Forward module excluded from build, skipping");
|
||||||
|
return skipExcludedModuleConfig(buf);
|
||||||
|
#endif
|
||||||
case meshtastic_ModuleConfig_range_test_tag:
|
case meshtastic_ModuleConfig_range_test_tag:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
||||||
LOG_DEBUG("Send module config: range test");
|
LOG_DEBUG("Send module config: range test");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
|
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Range Test module excluded from build, skipping");
|
||||||
|
return skipExcludedModuleConfig(buf);
|
||||||
|
#endif
|
||||||
case meshtastic_ModuleConfig_telemetry_tag:
|
case meshtastic_ModuleConfig_telemetry_tag:
|
||||||
LOG_DEBUG("Send module config: telemetry");
|
LOG_DEBUG("Send module config: telemetry");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_telemetry_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_telemetry_tag;
|
||||||
@@ -379,10 +409,15 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
|
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_audio_tag:
|
case meshtastic_ModuleConfig_audio_tag:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AUDIO
|
||||||
LOG_DEBUG("Send module config: audio");
|
LOG_DEBUG("Send module config: audio");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio;
|
fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Audio module excluded from build, skipping");
|
||||||
|
return skipExcludedModuleConfig(buf);
|
||||||
|
#endif
|
||||||
case meshtastic_ModuleConfig_remote_hardware_tag:
|
case meshtastic_ModuleConfig_remote_hardware_tag:
|
||||||
LOG_DEBUG("Send module config: remote hardware");
|
LOG_DEBUG("Send module config: remote hardware");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
||||||
@@ -399,15 +434,25 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_ambient_lighting_tag:
|
case meshtastic_ModuleConfig_ambient_lighting_tag:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
||||||
LOG_DEBUG("Send module config: ambient lighting");
|
LOG_DEBUG("Send module config: ambient lighting");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
fromRadioScratch.moduleConfig.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Ambient Lighting module excluded from build, skipping");
|
||||||
|
return skipExcludedModuleConfig(buf);
|
||||||
|
#endif
|
||||||
case meshtastic_ModuleConfig_paxcounter_tag:
|
case meshtastic_ModuleConfig_paxcounter_tag:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
LOG_DEBUG("Send module config: paxcounter");
|
LOG_DEBUG("Send module config: paxcounter");
|
||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.paxcounter = moduleConfig.paxcounter;
|
fromRadioScratch.moduleConfig.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Paxcounter module excluded from build, skipping");
|
||||||
|
return skipExcludedModuleConfig(buf);
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unknown module config type %d", config_state);
|
LOG_ERROR("Unknown module config type %d", config_state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,4 +172,7 @@ class PhoneAPI
|
|||||||
|
|
||||||
/// If the mesh service tells us fromNum has changed, tell the phone
|
/// If the mesh service tells us fromNum has changed, tell the phone
|
||||||
virtual int onNotify(uint32_t newValue) override;
|
virtual int onNotify(uint32_t newValue) override;
|
||||||
|
|
||||||
|
/// Helper function to skip excluded module configs and advance state
|
||||||
|
size_t skipExcludedModuleConfig(uint8_t *buf);
|
||||||
};
|
};
|
||||||
+11
-11
@@ -10,7 +10,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
#define RF95_MAX_POWER settingsMap[rf95_max_power]
|
#define RF95_MAX_POWER portduino_config.rf95_max_power
|
||||||
#endif
|
#endif
|
||||||
#ifndef RF95_MAX_POWER
|
#ifndef RF95_MAX_POWER
|
||||||
#define RF95_MAX_POWER 20
|
#define RF95_MAX_POWER 20
|
||||||
@@ -94,16 +94,16 @@ void RF95Interface::setTransmitEnable(bool txon)
|
|||||||
#ifdef RF95_TXEN
|
#ifdef RF95_TXEN
|
||||||
digitalWrite(RF95_TXEN, txon ? 1 : 0);
|
digitalWrite(RF95_TXEN, txon ? 1 : 0);
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[txen_pin], txon ? 1 : 0);
|
digitalWrite(portduino_config.lora_txen_pin.pin, txon ? 1 : 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RF95_RXEN
|
#ifdef RF95_RXEN
|
||||||
digitalWrite(RF95_RXEN, txon ? 0 : 1);
|
digitalWrite(RF95_RXEN, txon ? 0 : 1);
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[rxen_pin], txon ? 0 : 1);
|
digitalWrite(portduino_config.lora_rxen_pin.pin, txon ? 0 : 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -164,13 +164,13 @@ bool RF95Interface::init()
|
|||||||
digitalWrite(RF95_RXEN, 1);
|
digitalWrite(RF95_RXEN, 1);
|
||||||
#endif
|
#endif
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
pinMode(settingsMap[txen_pin], OUTPUT);
|
pinMode(portduino_config.lora_txen_pin.pin, OUTPUT);
|
||||||
digitalWrite(settingsMap[txen_pin], 0);
|
digitalWrite(portduino_config.lora_txen_pin.pin, 0);
|
||||||
}
|
}
|
||||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
|
||||||
pinMode(settingsMap[rxen_pin], OUTPUT);
|
pinMode(portduino_config.lora_rxen_pin.pin, OUTPUT);
|
||||||
digitalWrite(settingsMap[rxen_pin], 0);
|
digitalWrite(portduino_config.lora_rxen_pin.pin, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
setTransmitEnable(false);
|
setTransmitEnable(false);
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
|||||||
|
|
||||||
int state = iface->readData((uint8_t *)&radioBuffer, length);
|
int state = iface->readData((uint8_t *)&radioBuffer, length);
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[logoutputlevel] == level_trace) {
|
if (portduino_config.logoutputlevel == level_trace) {
|
||||||
printBytes("Raw incoming packet: ", (uint8_t *)&radioBuffer, length);
|
printBytes("Raw incoming packet: ", (uint8_t *)&radioBuffer, length);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
|||||||
// marked as wantAck
|
// marked as wantAck
|
||||||
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, old->packet->channel);
|
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, old->packet->channel);
|
||||||
|
|
||||||
stopRetransmission(key);
|
// Only stop retransmissions if the rebroadcast came via LoRa
|
||||||
|
if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA) {
|
||||||
|
stopRetransmission(key);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Didn't find pending packet");
|
LOG_DEBUG("Didn't find pending packet");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -446,7 +446,7 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
|
|||||||
#if ENABLE_JSON_LOGGING
|
#if ENABLE_JSON_LOGGING
|
||||||
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
|
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
if (settingsStrings[traceFilename] != "" || settingsMap[logoutputlevel] == level_trace) {
|
if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) {
|
||||||
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
|
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -685,7 +685,7 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
|||||||
LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str());
|
LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str());
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
// Even ignored packets get logged in the trace
|
// Even ignored packets get logged in the trace
|
||||||
if (settingsStrings[traceFilename] != "" || settingsMap[logoutputlevel] == level_trace) {
|
if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) {
|
||||||
p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone
|
p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone
|
||||||
LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str());
|
LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#include "STM32WLE5JCInterface.h"
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#ifdef ARCH_STM32WL
|
||||||
|
#include "STM32WLE5JCInterface.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
#ifndef STM32WLx_MAX_POWER
|
#ifndef STM32WLx_MAX_POWER
|
||||||
#define STM32WLx_MAX_POWER 22
|
#define STM32WLx_MAX_POWER 22
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_STM32WL
|
|
||||||
|
|
||||||
STM32WLE5JCInterface::STM32WLE5JCInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
|
STM32WLE5JCInterface::STM32WLE5JCInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
|
||||||
RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy)
|
RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy)
|
||||||
: SX126xInterface(hal, cs, irq, rst, busy)
|
: SX126xInterface(hal, cs, irq, rst, busy)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SX126xInterface.h"
|
|
||||||
|
|
||||||
#ifdef ARCH_STM32WL
|
#ifdef ARCH_STM32WL
|
||||||
|
#include "SX126xInterface.h"
|
||||||
|
#include "rfswitch.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our adapter for STM32WLE5JC radios
|
* Our adapter for STM32WLE5JC radios
|
||||||
@@ -16,13 +16,4 @@ class STM32WLE5JCInterface : public SX126xInterface<STM32WLx>
|
|||||||
virtual bool init() override;
|
virtual bool init() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* https://wiki.seeedstudio.com/LoRa-E5_STM32WLE5JC_Module/
|
|
||||||
* Wio-E5 module ONLY transmits through RFO_HP
|
|
||||||
* Receive: PA4=1, PA5=0
|
|
||||||
* Transmit(high output power, SMPS mode): PA4=0, PA5=1 */
|
|
||||||
static const RADIOLIB_PIN_TYPE rfswitch_pins[5] = {PA4, PA5, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
|
|
||||||
|
|
||||||
static const Module::RfSwitchMode_t rfswitch_table[4] = {
|
|
||||||
{STM32WLx::MODE_IDLE, {LOW, LOW}}, {STM32WLx::MODE_RX, {HIGH, LOW}}, {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, END_OF_MODE_TABLE};
|
|
||||||
|
|
||||||
#endif // ARCH_STM32WL
|
#endif // ARCH_STM32WL
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
|
||||||
// specified (may be dangerous if using external PA and SX126x power config forgotten)
|
// specified (may be dangerous if using external PA and SX126x power config forgotten)
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
#define SX126X_MAX_POWER settingsMap[sx126x_max_power]
|
#define SX126X_MAX_POWER portduino_config.sx126x_max_power
|
||||||
#endif
|
#endif
|
||||||
#ifndef SX126X_MAX_POWER
|
#ifndef SX126X_MAX_POWER
|
||||||
#define SX126X_MAX_POWER 22
|
#define SX126X_MAX_POWER 22
|
||||||
@@ -53,10 +53,10 @@ template <typename T> bool SX126xInterface<T>::init()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
|
tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000;
|
||||||
if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_sx126x_ant_sw_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[sx126x_ant_sw_pin], HIGH);
|
digitalWrite(portduino_config.lora_sx126x_ant_sw_pin.pin, HIGH);
|
||||||
pinMode(settingsMap[sx126x_ant_sw_pin], OUTPUT);
|
pinMode(portduino_config.lora_sx126x_ant_sw_pin.pin, OUTPUT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (tcxoVoltage == 0.0)
|
if (tcxoVoltage == 0.0)
|
||||||
@@ -98,7 +98,7 @@ template <typename T> bool SX126xInterface<T>::init()
|
|||||||
bool dio2AsRfSwitch = true;
|
bool dio2AsRfSwitch = true;
|
||||||
#elif defined(ARCH_PORTDUINO)
|
#elif defined(ARCH_PORTDUINO)
|
||||||
bool dio2AsRfSwitch = false;
|
bool dio2AsRfSwitch = false;
|
||||||
if (settingsMap[dio2_as_rf_switch]) {
|
if (portduino_config.dio2_as_rf_switch) {
|
||||||
dio2AsRfSwitch = true;
|
dio2AsRfSwitch = true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -112,9 +112,9 @@ template <typename T> bool SX126xInterface<T>::init()
|
|||||||
// no effect
|
// no effect
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (res == RADIOLIB_ERR_NONE) {
|
if (res == RADIOLIB_ERR_NONE) {
|
||||||
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen_pin],
|
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", portduino_config.lora_rxen_pin.pin,
|
||||||
settingsMap[txen_pin]);
|
portduino_config.lora_txen_pin.pin);
|
||||||
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]);
|
lora.setRfSwitchPins(portduino_config.lora_rxen_pin.pin, portduino_config.lora_txen_pin.pin);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#ifndef SX126X_RXEN
|
#ifndef SX126X_RXEN
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
// Particular boards might define a different max power based on what their hardware can do
|
// Particular boards might define a different max power based on what their hardware can do
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
#define SX128X_MAX_POWER settingsMap[sx128x_max_power]
|
#define SX128X_MAX_POWER portduino_config.sx128x_max_power
|
||||||
#endif
|
#endif
|
||||||
#ifndef SX128X_MAX_POWER
|
#ifndef SX128X_MAX_POWER
|
||||||
#define SX128X_MAX_POWER 13
|
#define SX128X_MAX_POWER 13
|
||||||
@@ -41,13 +41,13 @@ template <typename T> bool SX128xInterface<T>::init()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
|
||||||
pinMode(settingsMap[rxen_pin], OUTPUT);
|
pinMode(portduino_config.lora_rxen_pin.pin, OUTPUT);
|
||||||
digitalWrite(settingsMap[rxen_pin], LOW); // Set low before becoming an output
|
digitalWrite(portduino_config.lora_rxen_pin.pin, LOW); // Set low before becoming an output
|
||||||
}
|
}
|
||||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
pinMode(settingsMap[txen_pin], OUTPUT);
|
pinMode(portduino_config.lora_txen_pin.pin, OUTPUT);
|
||||||
digitalWrite(settingsMap[txen_pin], LOW); // Set low before becoming an output
|
digitalWrite(portduino_config.lora_txen_pin.pin, LOW); // Set low before becoming an output
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
|
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
|
||||||
@@ -93,8 +93,9 @@ template <typename T> bool SX128xInterface<T>::init()
|
|||||||
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
|
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
|
||||||
}
|
}
|
||||||
#elif ARCH_PORTDUINO
|
#elif ARCH_PORTDUINO
|
||||||
if (res == RADIOLIB_ERR_NONE && settingsMap[rxen_pin] != RADIOLIB_NC && settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (res == RADIOLIB_ERR_NONE && portduino_config.lora_rxen_pin.pin != RADIOLIB_NC &&
|
||||||
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]);
|
portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
|
lora.setRfSwitchPins(portduino_config.lora_rxen_pin.pin, portduino_config.lora_txen_pin.pin);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -174,11 +175,11 @@ template <typename T> void SX128xInterface<T>::setStandby()
|
|||||||
LOG_ERROR("SX128x standby %s%d", radioLibErr, err);
|
LOG_ERROR("SX128x standby %s%d", radioLibErr, err);
|
||||||
assert(err == RADIOLIB_ERR_NONE);
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[rxen_pin], LOW);
|
digitalWrite(portduino_config.lora_rxen_pin.pin, LOW);
|
||||||
}
|
}
|
||||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[txen_pin], LOW);
|
digitalWrite(portduino_config.lora_txen_pin.pin, LOW);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
|
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
|
||||||
@@ -210,11 +211,11 @@ template <typename T> void SX128xInterface<T>::addReceiveMetadata(meshtastic_Mes
|
|||||||
template <typename T> void SX128xInterface<T>::configHardwareForSend()
|
template <typename T> void SX128xInterface<T>::configHardwareForSend()
|
||||||
{
|
{
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[txen_pin], HIGH);
|
digitalWrite(portduino_config.lora_txen_pin.pin, HIGH);
|
||||||
}
|
}
|
||||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[rxen_pin], LOW);
|
digitalWrite(portduino_config.lora_rxen_pin.pin, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -241,11 +242,11 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
|||||||
setStandby();
|
setStandby();
|
||||||
|
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[rxen_pin], HIGH);
|
digitalWrite(portduino_config.lora_rxen_pin.pin, HIGH);
|
||||||
}
|
}
|
||||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
|
||||||
digitalWrite(settingsMap[txen_pin], LOW);
|
digitalWrite(portduino_config.lora_txen_pin.pin, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
|||||||
in areas not already covered by other routers, or to bridge around problematic terrain,
|
in areas not already covered by other routers, or to bridge around problematic terrain,
|
||||||
but should not be given priority over other routers in order to avoid unnecessaraily
|
but should not be given priority over other routers in order to avoid unnecessaraily
|
||||||
consuming hops. */
|
consuming hops. */
|
||||||
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11
|
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11,
|
||||||
|
/* Description: Treats packets from or to favorited nodes as ROUTER, and all other packets as CLIENT.
|
||||||
|
Technical Details: Used for stronger attic/roof nodes to distribute messages more widely
|
||||||
|
from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes
|
||||||
|
where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node. */
|
||||||
|
meshtastic_Config_DeviceConfig_Role_CLIENT_BASE = 12
|
||||||
} meshtastic_Config_DeviceConfig_Role;
|
} meshtastic_Config_DeviceConfig_Role;
|
||||||
|
|
||||||
/* Defines the device's behavior for how messages are rebroadcast */
|
/* Defines the device's behavior for how messages are rebroadcast */
|
||||||
@@ -646,8 +651,8 @@ extern "C" {
|
|||||||
|
|
||||||
/* Helper constants for enums */
|
/* Helper constants for enums */
|
||||||
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
||||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_ROUTER_LATE
|
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_CLIENT_BASE
|
||||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_ROUTER_LATE+1))
|
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_CLIENT_BASE+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
|
||||||
|
|||||||
@@ -270,6 +270,10 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
|
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
|
||||||
https://heltec.org/project/meshsolar/ */
|
https://heltec.org/project/meshsolar/ */
|
||||||
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
|
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
|
||||||
|
/* Lilygo T-Echo Lite */
|
||||||
|
meshtastic_HardwareModel_T_ECHO_LITE = 109,
|
||||||
|
/* New Heltec LoRA32 with ESP32-S3 CPU */
|
||||||
|
meshtastic_HardwareModel_HELTEC_V4 = 110,
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
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.
|
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.
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|||||||
@@ -342,6 +342,11 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
|
|||||||
res->print(value->Stringify().c_str());
|
res->print(value->Stringify().c_str());
|
||||||
|
|
||||||
delete value;
|
delete value;
|
||||||
|
|
||||||
|
// Clean up the fileList to prevent memory leak
|
||||||
|
for (auto *val : fileList) {
|
||||||
|
delete val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
||||||
@@ -610,33 +615,38 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
|||||||
res->println("<pre>");
|
res->println("<pre>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper lambda to create JSON array and clean up memory properly
|
||||||
|
auto createJSONArrayFromLog = [](uint32_t *logArray, int count) -> JSONValue * {
|
||||||
|
JSONArray tempArray;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
tempArray.push_back(new JSONValue((int)logArray[i]));
|
||||||
|
}
|
||||||
|
JSONValue *result = new JSONValue(tempArray);
|
||||||
|
// Clean up original array to prevent memory leak
|
||||||
|
for (auto *val : tempArray) {
|
||||||
|
delete val;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// data->airtime->tx_log
|
// data->airtime->tx_log
|
||||||
JSONArray txLogValues;
|
|
||||||
uint32_t *logArray;
|
uint32_t *logArray;
|
||||||
logArray = airTime->airtimeReport(TX_LOG);
|
logArray = airTime->airtimeReport(TX_LOG);
|
||||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
JSONValue *txLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
|
||||||
txLogValues.push_back(new JSONValue((int)logArray[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// data->airtime->rx_log
|
// data->airtime->rx_log
|
||||||
JSONArray rxLogValues;
|
|
||||||
logArray = airTime->airtimeReport(RX_LOG);
|
logArray = airTime->airtimeReport(RX_LOG);
|
||||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
JSONValue *rxLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
|
||||||
rxLogValues.push_back(new JSONValue((int)logArray[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// data->airtime->rx_all_log
|
// data->airtime->rx_all_log
|
||||||
JSONArray rxAllLogValues;
|
|
||||||
logArray = airTime->airtimeReport(RX_ALL_LOG);
|
logArray = airTime->airtimeReport(RX_ALL_LOG);
|
||||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
JSONValue *rxAllLogJsonValue = createJSONArrayFromLog(logArray, airTime->getPeriodsToLog());
|
||||||
rxAllLogValues.push_back(new JSONValue((int)logArray[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// data->airtime
|
// data->airtime
|
||||||
JSONObject jsonObjAirtime;
|
JSONObject jsonObjAirtime;
|
||||||
jsonObjAirtime["tx_log"] = new JSONValue(txLogValues);
|
jsonObjAirtime["tx_log"] = txLogJsonValue;
|
||||||
jsonObjAirtime["rx_log"] = new JSONValue(rxLogValues);
|
jsonObjAirtime["rx_log"] = rxLogJsonValue;
|
||||||
jsonObjAirtime["rx_all_log"] = new JSONValue(rxAllLogValues);
|
jsonObjAirtime["rx_all_log"] = rxAllLogJsonValue;
|
||||||
jsonObjAirtime["channel_utilization"] = new JSONValue(airTime->channelUtilizationPercent());
|
jsonObjAirtime["channel_utilization"] = new JSONValue(airTime->channelUtilizationPercent());
|
||||||
jsonObjAirtime["utilization_tx"] = new JSONValue(airTime->utilizationTXPercent());
|
jsonObjAirtime["utilization_tx"] = new JSONValue(airTime->utilizationTXPercent());
|
||||||
jsonObjAirtime["seconds_since_boot"] = new JSONValue(int(airTime->getSecondsSinceBoot()));
|
jsonObjAirtime["seconds_since_boot"] = new JSONValue(int(airTime->getSecondsSinceBoot()));
|
||||||
@@ -765,6 +775,11 @@ void handleNodes(HTTPRequest *req, HTTPResponse *res)
|
|||||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||||
res->print(value->Stringify().c_str());
|
res->print(value->Stringify().c_str());
|
||||||
delete value;
|
delete value;
|
||||||
|
|
||||||
|
// Clean up the nodesArray to prevent memory leak
|
||||||
|
for (auto *val : nodesArray) {
|
||||||
|
delete val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -955,5 +970,10 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
|||||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||||
res->print(value->Stringify().c_str());
|
res->print(value->Stringify().c_str());
|
||||||
delete value;
|
delete value;
|
||||||
|
|
||||||
|
// Clean up the networkObjs to prevent memory leak
|
||||||
|
for (auto *val : networkObjs) {
|
||||||
|
delete val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -65,8 +65,8 @@ mail: marchammermann@googlemail.com
|
|||||||
#define DEFAULT_REALM "default_realm"
|
#define DEFAULT_REALM "default_realm"
|
||||||
#define PREFIX ""
|
#define PREFIX ""
|
||||||
|
|
||||||
#define KEY_PATH settingsStrings[websslkeypath].c_str()
|
#define KEY_PATH portduino_config.webserver_ssl_key_path.c_str()
|
||||||
#define CERT_PATH settingsStrings[websslcertpath].c_str()
|
#define CERT_PATH portduino_config.webserver_ssl_cert_path.c_str()
|
||||||
|
|
||||||
struct _file_config configWeb;
|
struct _file_config configWeb;
|
||||||
|
|
||||||
@@ -458,8 +458,8 @@ PiWebServerThread::PiWebServerThread()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingsMap[webserverport] != 0) {
|
if (portduino_config.webserverport != 0) {
|
||||||
webservport = settingsMap[webserverport];
|
webservport = portduino_config.webserverport;
|
||||||
LOG_INFO("Use webserver port from yaml config %i ", webservport);
|
LOG_INFO("Use webserver port from yaml config %i ", webservport);
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 9443");
|
LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 9443");
|
||||||
@@ -490,7 +490,7 @@ PiWebServerThread::PiWebServerThread()
|
|||||||
u_map_put(&configWeb.mime_types, ".ico", "image/x-icon");
|
u_map_put(&configWeb.mime_types, ".ico", "image/x-icon");
|
||||||
u_map_put(&configWeb.mime_types, ".svg", "image/svg+xml");
|
u_map_put(&configWeb.mime_types, ".svg", "image/svg+xml");
|
||||||
|
|
||||||
webrootpath = settingsStrings[webserverrootpath];
|
webrootpath = portduino_config.webserver_root_path;
|
||||||
|
|
||||||
configWeb.files_path = (char *)webrootpath.c_str();
|
configWeb.files_path = (char *)webrootpath.c_str();
|
||||||
configWeb.url_prefix = "";
|
configWeb.url_prefix = "";
|
||||||
|
|||||||
@@ -1040,19 +1040,32 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.payload_variant.serial = moduleConfig.serial;
|
res.get_module_config_response.payload_variant.serial = moduleConfig.serial;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
|
||||||
LOG_INFO("Get module config: External Notification");
|
LOG_INFO("Get module config: External Notification");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
|
||||||
res.get_module_config_response.payload_variant.external_notification = moduleConfig.external_notification;
|
res.get_module_config_response.payload_variant.external_notification = moduleConfig.external_notification;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("External Notification module excluded from build, skipping config");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||||
LOG_INFO("Get module config: Store & Forward");
|
LOG_INFO("Get module config: Store & Forward");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
|
||||||
res.get_module_config_response.payload_variant.store_forward = moduleConfig.store_forward;
|
res.get_module_config_response.payload_variant.store_forward = moduleConfig.store_forward;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Store & Forward module excluded from build, skipping config");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_RANGETEST_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_RANGETEST_CONFIG:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_RANGETEST
|
||||||
LOG_INFO("Get module config: Range Test");
|
LOG_INFO("Get module config: Range Test");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
|
||||||
res.get_module_config_response.payload_variant.range_test = moduleConfig.range_test;
|
res.get_module_config_response.payload_variant.range_test = moduleConfig.range_test;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Range Test module excluded from build, skipping config");
|
||||||
|
// Don't set payload variant - will result in empty response
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_TELEMETRY_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_TELEMETRY_CONFIG:
|
||||||
LOG_INFO("Get module config: Telemetry");
|
LOG_INFO("Get module config: Telemetry");
|
||||||
@@ -1065,9 +1078,13 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.payload_variant.canned_message = moduleConfig.canned_message;
|
res.get_module_config_response.payload_variant.canned_message = moduleConfig.canned_message;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AUDIO
|
||||||
LOG_INFO("Get module config: Audio");
|
LOG_INFO("Get module config: Audio");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
|
||||||
res.get_module_config_response.payload_variant.audio = moduleConfig.audio;
|
res.get_module_config_response.payload_variant.audio = moduleConfig.audio;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Audio module excluded from build, skipping config");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG:
|
||||||
LOG_INFO("Get module config: Remote Hardware");
|
LOG_INFO("Get module config: Remote Hardware");
|
||||||
@@ -1080,19 +1097,31 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
|
||||||
|
#if !(NO_EXT_GPIO || MESHTASTIC_EXCLUDE_DETECTIONSENSOR)
|
||||||
LOG_INFO("Get module config: Detection Sensor");
|
LOG_INFO("Get module config: Detection Sensor");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
||||||
res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Detection Sensor module excluded from build, skipping config");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_AMBIENTLIGHTING
|
||||||
LOG_INFO("Get module config: Ambient Lighting");
|
LOG_INFO("Get module config: Ambient Lighting");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
|
||||||
res.get_module_config_response.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
res.get_module_config_response.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Ambient Lighting module excluded from build, skipping config");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG:
|
case meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG:
|
||||||
|
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
LOG_INFO("Get module config: Paxcounter");
|
LOG_INFO("Get module config: Paxcounter");
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||||
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||||
|
#else
|
||||||
|
LOG_DEBUG("Paxcounter module excluded from build, skipping config");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr, bool battery_only);
|
extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr, bool force_no_invert,
|
||||||
|
bool show_date);
|
||||||
}
|
}
|
||||||
#if __has_include(<Adafruit_AHTX0.h>)
|
#if __has_include(<Adafruit_AHTX0.h>)
|
||||||
#include "Sensor/AHT10.h"
|
#include "Sensor/AHT10.h"
|
||||||
@@ -198,6 +199,13 @@ T1000xSensor t1000xSensor;
|
|||||||
IndicatorSensor indicatorSensor;
|
IndicatorSensor indicatorSensor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __has_include(<Adafruit_TSL2561_U.h>)
|
||||||
|
#include "Sensor/TSL2561Sensor.h"
|
||||||
|
TSL2561Sensor tsl2561Sensor;
|
||||||
|
#else
|
||||||
|
NullSensor tsl2561Sensor;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||||
|
|
||||||
@@ -296,6 +304,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||||||
result = max17048Sensor.runOnce();
|
result = max17048Sensor.runOnce();
|
||||||
if (cgRadSens.hasSensor())
|
if (cgRadSens.hasSensor())
|
||||||
result = cgRadSens.runOnce();
|
result = cgRadSens.runOnce();
|
||||||
|
if (tsl2561Sensor.hasSensor())
|
||||||
|
result = tsl2561Sensor.runOnce();
|
||||||
if (pct2075Sensor.hasSensor())
|
if (pct2075Sensor.hasSensor())
|
||||||
result = pct2075Sensor.runOnce();
|
result = pct2075Sensor.runOnce();
|
||||||
// this only works on the wismesh hub with the solar option. This is not an I2C sensor, so we don't need the
|
// this only works on the wismesh hub with the solar option. This is not an I2C sensor, so we don't need the
|
||||||
@@ -642,6 +652,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
|||||||
valid = valid && nau7802Sensor.getMetrics(m);
|
valid = valid && nau7802Sensor.getMetrics(m);
|
||||||
hasSensor = true;
|
hasSensor = true;
|
||||||
}
|
}
|
||||||
|
if (tsl2561Sensor.hasSensor()) {
|
||||||
|
valid = valid && tsl2561Sensor.getMetrics(m);
|
||||||
|
hasSensor = true;
|
||||||
|
}
|
||||||
if (aht10Sensor.hasSensor()) {
|
if (aht10Sensor.hasSensor()) {
|
||||||
if (!bmp280Sensor.hasSensor() && !bmp3xxSensor.hasSensor()) {
|
if (!bmp280Sensor.hasSensor() && !bmp3xxSensor.hasSensor()) {
|
||||||
valid = valid && aht10Sensor.getMetrics(m);
|
valid = valid && aht10Sensor.getMetrics(m);
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
int32_t HostMetricsModule::runOnce()
|
int32_t HostMetricsModule::runOnce()
|
||||||
{
|
{
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (settingsMap[hostMetrics_interval] == 0) {
|
if (portduino_config.hostMetrics_interval == 0) {
|
||||||
return disable();
|
return disable();
|
||||||
} else {
|
} else {
|
||||||
sendMetrics();
|
sendMetrics();
|
||||||
return 60 * 1000 * settingsMap[hostMetrics_interval];
|
return 60 * 1000 * portduino_config.hostMetrics_interval;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return disable();
|
return disable();
|
||||||
@@ -110,8 +110,8 @@ meshtastic_Telemetry HostMetricsModule::getHostMetrics()
|
|||||||
proc_loadavg.close();
|
proc_loadavg.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (settingsStrings[hostMetrics_user_command] != "") {
|
if (portduino_config.hostMetrics_user_command != "") {
|
||||||
std::string userCommandResult = exec(settingsStrings[hostMetrics_user_command].c_str());
|
std::string userCommandResult = exec(portduino_config.hostMetrics_user_command.c_str());
|
||||||
if (userCommandResult.length() > 1) {
|
if (userCommandResult.length() > 1) {
|
||||||
strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), sizeof(t.variant.host_metrics.user_string));
|
strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), sizeof(t.variant.host_metrics.user_string));
|
||||||
t.variant.host_metrics.user_string[sizeof(t.variant.host_metrics.user_string) - 1] = '\0';
|
t.variant.host_metrics.user_string[sizeof(t.variant.host_metrics.user_string) - 1] = '\0';
|
||||||
@@ -135,7 +135,7 @@ bool HostMetricsModule::sendMetrics()
|
|||||||
p->to = NODENUM_BROADCAST;
|
p->to = NODENUM_BROADCAST;
|
||||||
p->decoded.want_response = false;
|
p->decoded.want_response = false;
|
||||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||||
p->channel = settingsMap[hostMetrics_channel];
|
p->channel = portduino_config.hostMetrics_channel;
|
||||||
LOG_INFO("Send packet to mesh");
|
LOG_INFO("Send packet to mesh");
|
||||||
service->sendToMesh(p, RX_SRC_LOCAL, true);
|
service->sendToMesh(p, RX_SRC_LOCAL, true);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -24,7 +24,8 @@
|
|||||||
|
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr, bool battery_only);
|
extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr, bool force_no_invert,
|
||||||
|
bool show_date);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t PowerTelemetryModule::runOnce()
|
int32_t PowerTelemetryModule::runOnce()
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_TSL2561_U.h>)
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "TSL2561Sensor.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <Adafruit_TSL2561_U.h>
|
||||||
|
|
||||||
|
TSL2561Sensor::TSL2561Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_TSL2561, "TSL2561") {}
|
||||||
|
|
||||||
|
int32_t TSL2561Sensor::runOnce()
|
||||||
|
{
|
||||||
|
LOG_INFO("Init sensor: %s", sensorName);
|
||||||
|
if (!hasSensor()) {
|
||||||
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = tsl.begin(nodeTelemetrySensorsMap[sensorType].second);
|
||||||
|
|
||||||
|
return initI2CSensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSL2561Sensor::setup()
|
||||||
|
{
|
||||||
|
tsl.setGain(TSL2561_GAIN_1X);
|
||||||
|
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TSL2561Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||||
|
{
|
||||||
|
measurement->variant.environment_metrics.has_lux = true;
|
||||||
|
sensors_event_t event;
|
||||||
|
tsl.getEvent(&event);
|
||||||
|
measurement->variant.environment_metrics.lux = event.light;
|
||||||
|
LOG_INFO("Lux: %f", measurement->variant.environment_metrics.lux);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_TSL2561_U.h>)
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <Adafruit_TSL2561_U.h>
|
||||||
|
|
||||||
|
class TSL2561Sensor : public TelemetrySensor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// The magic number is a sensor id, the actual value doesn't matter
|
||||||
|
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_LOW, 12345);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void setup() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TSL2561Sensor();
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||||
|
|
||||||
#if defined(RAK_4631) && !defined(RAK2560) && __has_include(<Rak_BMX160.h>)
|
#if !defined(RAK2560) && __has_include(<Rak_BMX160.h>)
|
||||||
|
|
||||||
#include "Fusion/Fusion.h"
|
#include "Fusion/Fusion.h"
|
||||||
#include <Rak_BMX160.h>
|
#include <Rak_BMX160.h>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include "api/ServerAPI.h"
|
#include "api/ServerAPI.h"
|
||||||
#include "linux/gpio/LinuxGPIOPin.h"
|
#include "linux/gpio/LinuxGPIOPin.h"
|
||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
#include "yaml-cpp/yaml.h"
|
|
||||||
#include <ErriezCRC32.h>
|
#include <ErriezCRC32.h>
|
||||||
#include <Utility.h>
|
#include <Utility.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -28,14 +27,13 @@
|
|||||||
|
|
||||||
#include "platform/portduino/USBHal.h"
|
#include "platform/portduino/USBHal.h"
|
||||||
|
|
||||||
std::map<configNames, int> settingsMap;
|
|
||||||
std::map<configNames, std::string> settingsStrings;
|
|
||||||
portduino_config_struct portduino_config;
|
portduino_config_struct portduino_config;
|
||||||
std::ofstream traceFile;
|
std::ofstream traceFile;
|
||||||
Ch341Hal *ch341Hal = nullptr;
|
Ch341Hal *ch341Hal = nullptr;
|
||||||
char *configPath = nullptr;
|
char *configPath = nullptr;
|
||||||
char *optionMac = nullptr;
|
char *optionMac = nullptr;
|
||||||
bool verboseEnabled = false;
|
bool verboseEnabled = false;
|
||||||
|
bool yamlOnly = false;
|
||||||
|
|
||||||
const char *argp_program_version = optstr(APP_VERSION);
|
const char *argp_program_version = optstr(APP_VERSION);
|
||||||
|
|
||||||
@@ -75,6 +73,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
|||||||
case 'v':
|
case 'v':
|
||||||
verboseEnabled = true;
|
verboseEnabled = true;
|
||||||
break;
|
break;
|
||||||
|
case 'y':
|
||||||
|
yamlOnly = true;
|
||||||
|
break;
|
||||||
case ARGP_KEY_ARG:
|
case ARGP_KEY_ARG:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
@@ -90,6 +91,7 @@ void portduinoCustomInit()
|
|||||||
{"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"},
|
{"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"},
|
||||||
{"sim", 's', 0, 0, "Run in Simulated radio mode"},
|
{"sim", 's', 0, 0, "Run in Simulated radio mode"},
|
||||||
{"verbose", 'v', 0, 0, "Set log level to full debug"},
|
{"verbose", 'v', 0, 0, "Set log level to full debug"},
|
||||||
|
{"output-yaml", 'y', 0, 0, "Output config yaml and exit"},
|
||||||
{0}};
|
{0}};
|
||||||
static void *childArguments;
|
static void *childArguments;
|
||||||
static char doc[] = "Meshtastic native build.";
|
static char doc[] = "Meshtastic native build.";
|
||||||
@@ -115,8 +117,8 @@ void getMacAddr(uint8_t *dmac)
|
|||||||
dmac[4] = hwId >> 8;
|
dmac[4] = hwId >> 8;
|
||||||
dmac[5] = hwId & 0xff;
|
dmac[5] = hwId & 0xff;
|
||||||
}
|
}
|
||||||
} else if (settingsStrings[mac_address].length() > 11) {
|
} else if (portduino_config.mac_address.length() > 11) {
|
||||||
MAC_from_string(settingsStrings[mac_address], dmac);
|
MAC_from_string(portduino_config.mac_address, dmac);
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -148,89 +150,46 @@ void getMacAddr(uint8_t *dmac)
|
|||||||
*/
|
*/
|
||||||
void portduinoSetup()
|
void portduinoSetup()
|
||||||
{
|
{
|
||||||
printf("Set up Meshtastic on Portduino...\n");
|
|
||||||
int max_GPIO = 0;
|
int max_GPIO = 0;
|
||||||
const configNames GPIO_lines[] = {cs_pin,
|
|
||||||
irq_pin,
|
|
||||||
busy_pin,
|
|
||||||
reset_pin,
|
|
||||||
sx126x_ant_sw_pin,
|
|
||||||
txen_pin,
|
|
||||||
rxen_pin,
|
|
||||||
displayDC,
|
|
||||||
displayCS,
|
|
||||||
displayBacklight,
|
|
||||||
displayBacklightPWMChannel,
|
|
||||||
displayReset,
|
|
||||||
touchscreenCS,
|
|
||||||
touchscreenIRQ,
|
|
||||||
userButtonPin,
|
|
||||||
tbUpPin,
|
|
||||||
tbDownPin,
|
|
||||||
tbLeftPin,
|
|
||||||
tbRightPin,
|
|
||||||
tbPressPin};
|
|
||||||
|
|
||||||
std::string gpioChipName = "gpiochip";
|
std::string gpioChipName = "gpiochip";
|
||||||
settingsStrings[i2cdev] = "";
|
portduino_config.displayPanel = no_screen;
|
||||||
settingsStrings[keyboardDevice] = "";
|
|
||||||
settingsStrings[pointerDevice] = "";
|
|
||||||
settingsStrings[webserverrootpath] = "";
|
|
||||||
settingsStrings[spidev] = "";
|
|
||||||
settingsStrings[displayspidev] = "";
|
|
||||||
settingsMap[spiSpeed] = 2000000;
|
|
||||||
settingsMap[ascii_logs] = !isatty(1);
|
|
||||||
settingsMap[displayPanel] = no_screen;
|
|
||||||
settingsMap[touchscreenModule] = no_touchscreen;
|
|
||||||
settingsMap[tbUpPin] = RADIOLIB_NC;
|
|
||||||
settingsMap[tbDownPin] = RADIOLIB_NC;
|
|
||||||
settingsMap[tbLeftPin] = RADIOLIB_NC;
|
|
||||||
settingsMap[tbRightPin] = RADIOLIB_NC;
|
|
||||||
settingsMap[tbPressPin] = RADIOLIB_NC;
|
|
||||||
|
|
||||||
YAML::Node yamlConfig;
|
|
||||||
|
|
||||||
if (portduino_config.force_simradio == true) {
|
if (portduino_config.force_simradio == true) {
|
||||||
settingsMap[use_simradio] = true;
|
portduino_config.lora_module = use_simradio;
|
||||||
} else if (configPath != nullptr) {
|
} else if (configPath != nullptr) {
|
||||||
if (loadConfig(configPath)) {
|
if (loadConfig(configPath)) {
|
||||||
std::cout << "Using " << configPath << " as config file" << std::endl;
|
if (!yamlOnly)
|
||||||
|
std::cout << "Using " << configPath << " as config file" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Unable to use " << configPath << " as config file" << std::endl;
|
std::cout << "Unable to use " << configPath << " as config file" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (access("config.yaml", R_OK) == 0) {
|
} else if (access("config.yaml", R_OK) == 0) {
|
||||||
if (loadConfig("config.yaml")) {
|
if (loadConfig("config.yaml")) {
|
||||||
std::cout << "Using local config.yaml as config file" << std::endl;
|
if (!yamlOnly)
|
||||||
|
std::cout << "Using local config.yaml as config file" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Unable to use local config.yaml as config file" << std::endl;
|
std::cout << "Unable to use local config.yaml as config file" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) {
|
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) {
|
||||||
if (loadConfig("/etc/meshtasticd/config.yaml")) {
|
if (loadConfig("/etc/meshtasticd/config.yaml")) {
|
||||||
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
|
if (!yamlOnly)
|
||||||
|
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Unable to use /etc/meshtasticd/config.yaml as config file" << std::endl;
|
std::cout << "Unable to use /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "No 'config.yaml' found..." << std::endl;
|
if (!yamlOnly)
|
||||||
settingsMap[use_simradio] = true;
|
std::cout << "No 'config.yaml' found..." << std::endl;
|
||||||
|
portduino_config.lora_module = use_simradio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingsMap[use_simradio] == true) {
|
if (portduino_config.config_directory != "") {
|
||||||
std::cout << "Running in simulated mode." << std::endl;
|
|
||||||
settingsMap[maxnodes] = 200; // Default to 200 nodes
|
|
||||||
settingsMap[logoutputlevel] = level_debug; // Default to debug
|
|
||||||
// Set the random seed equal to TCPPort to have a different seed per instance
|
|
||||||
randomSeed(TCPPort);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settingsStrings[config_directory] != "") {
|
|
||||||
std::string filetype = ".yaml";
|
std::string filetype = ".yaml";
|
||||||
for (const std::filesystem::directory_entry &entry :
|
for (const std::filesystem::directory_entry &entry :
|
||||||
std::filesystem::directory_iterator{settingsStrings[config_directory]}) {
|
std::filesystem::directory_iterator{portduino_config.config_directory}) {
|
||||||
if (ends_with(entry.path().string(), ".yaml")) {
|
if (ends_with(entry.path().string(), ".yaml")) {
|
||||||
std::cout << "Also using " << entry << " as additional config file" << std::endl;
|
std::cout << "Also using " << entry << " as additional config file" << std::endl;
|
||||||
loadConfig(entry.path().c_str());
|
loadConfig(entry.path().c_str());
|
||||||
@@ -238,15 +197,28 @@ void portduinoSetup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (yamlOnly) {
|
||||||
|
std::cout << portduino_config.emit_yaml() << std::endl;
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portduino_config.lora_module == use_simradio) {
|
||||||
|
std::cout << "Running in simulated mode." << std::endl;
|
||||||
|
portduino_config.MaxNodes = 200; // Default to 200 nodes
|
||||||
|
// Set the random seed equal to TCPPort to have a different seed per instance
|
||||||
|
randomSeed(TCPPort);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If LoRa `Module: auto` (default in config.yaml),
|
// If LoRa `Module: auto` (default in config.yaml),
|
||||||
// attempt to auto config based on Product Strings
|
// attempt to auto config based on Product Strings
|
||||||
if (settingsMap[use_autoconf] == true) {
|
if (portduino_config.lora_module == use_autoconf) {
|
||||||
char autoconf_product[96] = {0};
|
char autoconf_product[96] = {0};
|
||||||
// Try CH341
|
// Try CH341
|
||||||
try {
|
try {
|
||||||
std::cout << "autoconf: Looking for CH341 device..." << std::endl;
|
std::cout << "autoconf: Looking for CH341 device..." << std::endl;
|
||||||
ch341Hal =
|
ch341Hal = new Ch341Hal(0, portduino_config.lora_usb_serial_num, portduino_config.lora_usb_vid,
|
||||||
new Ch341Hal(0, settingsStrings[lora_usb_serial_num], settingsMap[lora_usb_vid], settingsMap[lora_usb_pid]);
|
portduino_config.lora_usb_pid);
|
||||||
ch341Hal->getProductString(autoconf_product, 95);
|
ch341Hal->getProductString(autoconf_product, 95);
|
||||||
delete ch341Hal;
|
delete ch341Hal;
|
||||||
std::cout << "autoconf: Found CH341 device " << autoconf_product << std::endl;
|
std::cout << "autoconf: Found CH341 device " << autoconf_product << std::endl;
|
||||||
@@ -323,7 +295,7 @@ void portduinoSetup()
|
|||||||
if (mac_start != nullptr) {
|
if (mac_start != nullptr) {
|
||||||
std::cout << "autoconf: Found mac data " << mac_start << std::endl;
|
std::cout << "autoconf: Found mac data " << mac_start << std::endl;
|
||||||
if (strlen(mac_start) == 12)
|
if (strlen(mac_start) == 12)
|
||||||
settingsStrings[mac_address] = std::string(mac_start);
|
portduino_config.mac_address = std::string(mac_start);
|
||||||
}
|
}
|
||||||
if (devID_start != nullptr) {
|
if (devID_start != nullptr) {
|
||||||
std::cout << "autoconf: Found deviceid data " << devID_start << std::endl;
|
std::cout << "autoconf: Found deviceid data " << devID_start << std::endl;
|
||||||
@@ -354,7 +326,7 @@ void portduinoSetup()
|
|||||||
std::cerr << "autoconf: Unable to find config for " << autoconf_product << std::endl;
|
std::cerr << "autoconf: Unable to find config for " << autoconf_product << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (loadConfig((settingsStrings[available_directory] + product_config).c_str())) {
|
if (loadConfig((portduino_config.available_directory + product_config).c_str())) {
|
||||||
std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl;
|
std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "autoconf: Unable to use " << product_config << " as config file for " << autoconf_product
|
std::cerr << "autoconf: Unable to use " << product_config << " as config file for " << autoconf_product
|
||||||
@@ -363,15 +335,16 @@ void portduinoSetup()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "autoconf: Could not locate any devices" << std::endl;
|
std::cerr << "autoconf: Could not locate any devices" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're using a usermode driver, we need to initialize it here, to get a serial number back for mac address
|
// if we're using a usermode driver, we need to initialize it here, to get a serial number back for mac address
|
||||||
uint8_t dmac[6] = {0};
|
uint8_t dmac[6] = {0};
|
||||||
if (settingsStrings[spidev] == "ch341") {
|
if (portduino_config.lora_spi_dev == "ch341") {
|
||||||
try {
|
try {
|
||||||
ch341Hal =
|
ch341Hal = new Ch341Hal(0, portduino_config.lora_usb_serial_num, portduino_config.lora_usb_vid,
|
||||||
new Ch341Hal(0, settingsStrings[lora_usb_serial_num], settingsMap[lora_usb_vid], settingsMap[lora_usb_pid]);
|
portduino_config.lora_usb_pid);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
std::cerr << "Could not initialize CH341 device!" << std::endl;
|
std::cerr << "Could not initialize CH341 device!" << std::endl;
|
||||||
@@ -383,7 +356,7 @@ void portduinoSetup()
|
|||||||
char product_string[96] = {0};
|
char product_string[96] = {0};
|
||||||
ch341Hal->getProductString(product_string, 95);
|
ch341Hal->getProductString(product_string, 95);
|
||||||
std::cout << "CH341 Product " << product_string << std::endl;
|
std::cout << "CH341 Product " << product_string << std::endl;
|
||||||
if (strlen(serial) == 8 && settingsStrings[mac_address].length() < 12) {
|
if (strlen(serial) == 8 && portduino_config.mac_address.length() < 12) {
|
||||||
uint8_t hash[32] = {0};
|
uint8_t hash[32] = {0};
|
||||||
memcpy(hash, serial, 8);
|
memcpy(hash, serial, 8);
|
||||||
crypto->hash(hash, 8);
|
crypto->hash(hash, 8);
|
||||||
@@ -395,7 +368,7 @@ void portduinoSetup()
|
|||||||
dmac[5] = hash[5];
|
dmac[5] = hash[5];
|
||||||
char macBuf[13] = {0};
|
char macBuf[13] = {0};
|
||||||
sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
|
sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||||
settingsStrings[mac_address] = macBuf;
|
portduino_config.mac_address = macBuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,100 +382,38 @@ void portduinoSetup()
|
|||||||
// Rather important to set this, if not running simulated.
|
// Rather important to set this, if not running simulated.
|
||||||
randomSeed(time(NULL));
|
randomSeed(time(NULL));
|
||||||
|
|
||||||
std::string defaultGpioChipName = gpioChipName + std::to_string(settingsMap[default_gpiochip]);
|
std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip);
|
||||||
|
for (auto i : portduino_config.all_pins) {
|
||||||
for (configNames i : GPIO_lines) {
|
if (i->enabled && i->pin > max_GPIO)
|
||||||
if (settingsMap.count(i) && settingsMap[i] > max_GPIO)
|
max_GPIO = i->pin;
|
||||||
max_GPIO = settingsMap[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
||||||
|
|
||||||
// Need to bind all the configured GPIO pins so they're not simulated
|
// Need to bind all the configured GPIO pins so they're not simulated
|
||||||
// TODO: If one of these fails, we should log and terminate
|
// TODO: If one of these fails, we should log and terminate
|
||||||
if (settingsMap.count(userButtonPin) > 0 && settingsMap[userButtonPin] != RADIOLIB_NC) {
|
for (auto i : portduino_config.all_pins) {
|
||||||
if (initGPIOPin(settingsMap[userButtonPin], defaultGpioChipName, settingsMap[userButtonPin]) != ERRNO_OK) {
|
if (i->enabled)
|
||||||
settingsMap[userButtonPin] = RADIOLIB_NC;
|
if (initGPIOPin(i->pin, gpioChipName + std::to_string(i->gpiochip), i->line) != ERRNO_OK) {
|
||||||
}
|
printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i->line);
|
||||||
}
|
exit(EXIT_FAILURE);
|
||||||
if (settingsMap.count(tbUpPin) > 0 && settingsMap[tbUpPin] != RADIOLIB_NC) {
|
}
|
||||||
if (initGPIOPin(settingsMap[tbUpPin], defaultGpioChipName, settingsMap[tbUpPin]) != ERRNO_OK) {
|
|
||||||
settingsMap[tbUpPin] = RADIOLIB_NC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (settingsMap.count(tbDownPin) > 0 && settingsMap[tbDownPin] != RADIOLIB_NC) {
|
|
||||||
if (initGPIOPin(settingsMap[tbDownPin], defaultGpioChipName, settingsMap[tbDownPin]) != ERRNO_OK) {
|
|
||||||
settingsMap[tbDownPin] = RADIOLIB_NC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (settingsMap.count(tbLeftPin) > 0 && settingsMap[tbLeftPin] != RADIOLIB_NC) {
|
|
||||||
if (initGPIOPin(settingsMap[tbLeftPin], defaultGpioChipName, settingsMap[tbLeftPin]) != ERRNO_OK) {
|
|
||||||
settingsMap[tbLeftPin] = RADIOLIB_NC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (settingsMap.count(tbRightPin) > 0 && settingsMap[tbRightPin] != RADIOLIB_NC) {
|
|
||||||
if (initGPIOPin(settingsMap[tbRightPin], defaultGpioChipName, settingsMap[tbRightPin]) != ERRNO_OK) {
|
|
||||||
settingsMap[tbRightPin] = RADIOLIB_NC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (settingsMap.count(tbPressPin) > 0 && settingsMap[tbPressPin] != RADIOLIB_NC) {
|
|
||||||
if (initGPIOPin(settingsMap[tbPressPin], defaultGpioChipName, settingsMap[tbPressPin]) != ERRNO_OK) {
|
|
||||||
settingsMap[tbPressPin] = RADIOLIB_NC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (settingsMap[displayPanel] != no_screen) {
|
|
||||||
if (settingsMap[displayCS] > 0)
|
|
||||||
initGPIOPin(settingsMap[displayCS], defaultGpioChipName, settingsMap[displayCS]);
|
|
||||||
if (settingsMap[displayDC] > 0)
|
|
||||||
initGPIOPin(settingsMap[displayDC], defaultGpioChipName, settingsMap[displayDC]);
|
|
||||||
if (settingsMap[displayBacklight] > 0)
|
|
||||||
initGPIOPin(settingsMap[displayBacklight], defaultGpioChipName, settingsMap[displayBacklight]);
|
|
||||||
if (settingsMap[displayReset] > 0)
|
|
||||||
initGPIOPin(settingsMap[displayReset], defaultGpioChipName, settingsMap[displayReset]);
|
|
||||||
}
|
|
||||||
if (settingsMap[touchscreenModule] != no_touchscreen) {
|
|
||||||
if (settingsMap[touchscreenCS] > 0)
|
|
||||||
initGPIOPin(settingsMap[touchscreenCS], defaultGpioChipName, settingsMap[touchscreenCS]);
|
|
||||||
if (settingsMap[touchscreenIRQ] > 0)
|
|
||||||
initGPIOPin(settingsMap[touchscreenIRQ], defaultGpioChipName, settingsMap[touchscreenIRQ]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
||||||
if (settingsStrings[spidev] != "" && settingsStrings[spidev] != "ch341") {
|
if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
|
||||||
const struct {
|
SPI.begin(portduino_config.lora_spi_dev.c_str());
|
||||||
configNames pin;
|
|
||||||
configNames gpiochip;
|
|
||||||
configNames line;
|
|
||||||
} pinMappings[] = {{cs_pin, cs_gpiochip, cs_line},
|
|
||||||
{irq_pin, irq_gpiochip, irq_line},
|
|
||||||
{busy_pin, busy_gpiochip, busy_line},
|
|
||||||
{reset_pin, reset_gpiochip, reset_line},
|
|
||||||
{rxen_pin, rxen_gpiochip, rxen_line},
|
|
||||||
{txen_pin, txen_gpiochip, txen_line},
|
|
||||||
{sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line}};
|
|
||||||
for (auto &pinMap : pinMappings) {
|
|
||||||
auto setMapIter = settingsMap.find(pinMap.pin);
|
|
||||||
if (setMapIter != settingsMap.end() && setMapIter->second != RADIOLIB_NC) {
|
|
||||||
if (initGPIOPin(setMapIter->second, gpioChipName + std::to_string(settingsMap[pinMap.gpiochip]),
|
|
||||||
settingsMap[pinMap.line]) != ERRNO_OK) {
|
|
||||||
printf("Error setting pin number %d. It may not exist, or may already be in use.\n",
|
|
||||||
settingsMap[pinMap.line]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SPI.begin(settingsStrings[spidev].c_str());
|
|
||||||
}
|
}
|
||||||
if (settingsStrings[traceFilename] != "") {
|
if (portduino_config.traceFilename != "") {
|
||||||
try {
|
try {
|
||||||
traceFile.open(settingsStrings[traceFilename], std::ios::out | std::ios::app);
|
traceFile.open(portduino_config.traceFilename, std::ios::out | std::ios::app);
|
||||||
} catch (std::ofstream::failure &e) {
|
} catch (std::ofstream::failure &e) {
|
||||||
std::cout << "*** traceFile Exception " << e.what() << std::endl;
|
std::cout << "*** traceFile Exception " << e.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verboseEnabled && settingsMap[logoutputlevel] != level_trace) {
|
if (verboseEnabled && portduino_config.logoutputlevel != level_trace) {
|
||||||
settingsMap[logoutputlevel] = level_debug;
|
portduino_config.logoutputlevel = level_debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -537,99 +448,78 @@ bool loadConfig(const char *configPath)
|
|||||||
yamlConfig = YAML::LoadFile(configPath);
|
yamlConfig = YAML::LoadFile(configPath);
|
||||||
if (yamlConfig["Logging"]) {
|
if (yamlConfig["Logging"]) {
|
||||||
if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "trace") {
|
if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "trace") {
|
||||||
settingsMap[logoutputlevel] = level_trace;
|
portduino_config.logoutputlevel = level_trace;
|
||||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") {
|
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") {
|
||||||
settingsMap[logoutputlevel] = level_debug;
|
portduino_config.logoutputlevel = level_debug;
|
||||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") {
|
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") {
|
||||||
settingsMap[logoutputlevel] = level_info;
|
portduino_config.logoutputlevel = level_info;
|
||||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") {
|
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") {
|
||||||
settingsMap[logoutputlevel] = level_warn;
|
portduino_config.logoutputlevel = level_warn;
|
||||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") {
|
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") {
|
||||||
settingsMap[logoutputlevel] = level_error;
|
portduino_config.logoutputlevel = level_error;
|
||||||
}
|
}
|
||||||
settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
|
portduino_config.traceFilename = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
|
||||||
if (yamlConfig["Logging"]["AsciiLogs"]) {
|
if (yamlConfig["Logging"]["AsciiLogs"]) {
|
||||||
// Default is !isatty(1) but can be set explicitly in config.yaml
|
// Default is !isatty(1) but can be set explicitly in config.yaml
|
||||||
settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
|
portduino_config.ascii_logs = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
|
||||||
|
portduino_config.ascii_logs_explicit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["Lora"]) {
|
if (yamlConfig["Lora"]) {
|
||||||
const struct {
|
|
||||||
configNames cfgName;
|
|
||||||
std::string strName;
|
|
||||||
} loraModules[] = {{use_simradio, "sim"}, {use_autoconf, "auto"}, {use_rf95, "RF95"}, {use_sx1262, "sx1262"},
|
|
||||||
{use_sx1268, "sx1268"}, {use_sx1280, "sx1280"}, {use_lr1110, "lr1110"}, {use_lr1120, "lr1120"},
|
|
||||||
{use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
|
||||||
for (auto &loraModule : loraModules) {
|
|
||||||
settingsMap[loraModule.cfgName] = false;
|
|
||||||
}
|
|
||||||
if (yamlConfig["Lora"]["Module"]) {
|
if (yamlConfig["Lora"]["Module"]) {
|
||||||
for (auto &loraModule : loraModules) {
|
for (auto &loraModule : portduino_config.loraModules) {
|
||||||
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.strName) {
|
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.second) {
|
||||||
settingsMap[loraModule.cfgName] = true;
|
portduino_config.lora_module = loraModule.first;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (yamlConfig["Lora"]["SX126X_MAX_POWER"])
|
||||||
|
portduino_config.sx126x_max_power = yamlConfig["Lora"]["SX126X_MAX_POWER"].as<int>(22);
|
||||||
|
if (yamlConfig["Lora"]["SX128X_MAX_POWER"])
|
||||||
|
portduino_config.sx128x_max_power = yamlConfig["Lora"]["SX128X_MAX_POWER"].as<int>(13);
|
||||||
|
if (yamlConfig["Lora"]["LR1110_MAX_POWER"])
|
||||||
|
portduino_config.lr1110_max_power = yamlConfig["Lora"]["LR1110_MAX_POWER"].as<int>(22);
|
||||||
|
if (yamlConfig["Lora"]["LR1120_MAX_POWER"])
|
||||||
|
portduino_config.lr1120_max_power = yamlConfig["Lora"]["LR1120_MAX_POWER"].as<int>(13);
|
||||||
|
if (yamlConfig["Lora"]["RF95_MAX_POWER"])
|
||||||
|
portduino_config.rf95_max_power = yamlConfig["Lora"]["RF95_MAX_POWER"].as<int>(20);
|
||||||
|
|
||||||
settingsMap[sx126x_max_power] = yamlConfig["Lora"]["SX126X_MAX_POWER"].as<int>(22);
|
if (portduino_config.lora_module != use_autoconf && portduino_config.lora_module != use_simradio &&
|
||||||
settingsMap[sx128x_max_power] = yamlConfig["Lora"]["SX128X_MAX_POWER"].as<int>(13);
|
!portduino_config.force_simradio) {
|
||||||
settingsMap[lr1110_max_power] = yamlConfig["Lora"]["LR1110_MAX_POWER"].as<int>(22);
|
portduino_config.dio2_as_rf_switch = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
|
||||||
settingsMap[lr1120_max_power] = yamlConfig["Lora"]["LR1120_MAX_POWER"].as<int>(13);
|
portduino_config.dio3_tcxo_voltage = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000;
|
||||||
settingsMap[rf95_max_power] = yamlConfig["Lora"]["RF95_MAX_POWER"].as<int>(20);
|
if (portduino_config.dio3_tcxo_voltage == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) {
|
||||||
|
portduino_config.dio3_tcxo_voltage = 1800; // default millivolts for "true"
|
||||||
|
}
|
||||||
|
|
||||||
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
|
// backwards API compatibility and to globally set gpiochip once
|
||||||
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000;
|
portduino_config.lora_default_gpiochip = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
||||||
if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) {
|
for (auto this_pin : portduino_config.all_pins) {
|
||||||
settingsMap[dio3_tcxo_voltage] = 1800; // default millivolts for "true"
|
if (this_pin->config_section == "Lora") {
|
||||||
}
|
readGPIOFromYaml(yamlConfig["Lora"][this_pin->config_name], *this_pin);
|
||||||
|
}
|
||||||
// backwards API compatibility and to globally set gpiochip once
|
|
||||||
int defaultGpioChip = settingsMap[default_gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
|
||||||
|
|
||||||
const struct {
|
|
||||||
configNames pin;
|
|
||||||
configNames gpiochip;
|
|
||||||
configNames line;
|
|
||||||
std::string strName;
|
|
||||||
} pinMappings[] = {
|
|
||||||
{cs_pin, cs_gpiochip, cs_line, "CS"},
|
|
||||||
{irq_pin, irq_gpiochip, irq_line, "IRQ"},
|
|
||||||
{busy_pin, busy_gpiochip, busy_line, "Busy"},
|
|
||||||
{reset_pin, reset_gpiochip, reset_line, "Reset"},
|
|
||||||
{txen_pin, txen_gpiochip, txen_line, "TXen"},
|
|
||||||
{rxen_pin, rxen_gpiochip, rxen_line, "RXen"},
|
|
||||||
{sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line, "SX126X_ANT_SW"},
|
|
||||||
};
|
|
||||||
for (auto &pinMap : pinMappings) {
|
|
||||||
if (yamlConfig["Lora"][pinMap.strName].IsMap()) {
|
|
||||||
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName]["pin"].as<int>(RADIOLIB_NC);
|
|
||||||
settingsMap[pinMap.line] = yamlConfig["Lora"][pinMap.strName]["line"].as<int>(settingsMap[pinMap.pin]);
|
|
||||||
settingsMap[pinMap.gpiochip] = yamlConfig["Lora"][pinMap.strName]["gpiochip"].as<int>(defaultGpioChip);
|
|
||||||
} else { // backwards API compatibility
|
|
||||||
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName].as<int>(RADIOLIB_NC);
|
|
||||||
settingsMap[pinMap.line] = settingsMap[pinMap.pin];
|
|
||||||
settingsMap[pinMap.gpiochip] = defaultGpioChip;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
|
portduino_config.spiSpeed = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
|
||||||
settingsStrings[lora_usb_serial_num] = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>("");
|
portduino_config.lora_usb_serial_num = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>("");
|
||||||
settingsMap[lora_usb_pid] = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512);
|
portduino_config.lora_usb_pid = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512);
|
||||||
settingsMap[lora_usb_vid] = yamlConfig["Lora"]["USB_VID"].as<int>(0x1A86);
|
portduino_config.lora_usb_vid = yamlConfig["Lora"]["USB_VID"].as<int>(0x1A86);
|
||||||
|
|
||||||
settingsStrings[spidev] = yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
|
portduino_config.lora_spi_dev = yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
|
||||||
if (settingsStrings[spidev] != "ch341") {
|
if (portduino_config.lora_spi_dev != "ch341") {
|
||||||
settingsStrings[spidev] = "/dev/" + settingsStrings[spidev];
|
portduino_config.lora_spi_dev = "/dev/" + portduino_config.lora_spi_dev;
|
||||||
if (settingsStrings[spidev].length() == 14) {
|
if (portduino_config.lora_spi_dev.length() == 14) {
|
||||||
int x = settingsStrings[spidev].at(11) - '0';
|
int x = portduino_config.lora_spi_dev.at(11) - '0';
|
||||||
int y = settingsStrings[spidev].at(13) - '0';
|
int y = portduino_config.lora_spi_dev.at(13) - '0';
|
||||||
// Pretty sure this is always true
|
// Pretty sure this is always true
|
||||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||||
// I believe this bit of weirdness is specifically for the new GUI
|
// I believe this bit of weirdness is specifically for the new GUI
|
||||||
settingsMap[spidev] = x + y << 4;
|
portduino_config.lora_spi_dev_int = x + y << 4;
|
||||||
settingsMap[displayspidev] = settingsMap[spidev];
|
portduino_config.display_spi_dev_int = portduino_config.lora_spi_dev_int;
|
||||||
settingsMap[touchscreenspidev] = settingsMap[spidev];
|
portduino_config.touchscreen_spi_dev_int = portduino_config.lora_spi_dev_int;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -676,163 +566,152 @@ bool loadConfig(const char *configPath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["GPIO"]) {
|
readGPIOFromYaml(yamlConfig["GPIO"]["User"], portduino_config.userButtonPin);
|
||||||
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
|
|
||||||
}
|
|
||||||
if (yamlConfig["GPS"]) {
|
if (yamlConfig["GPS"]) {
|
||||||
std::string serialPath = yamlConfig["GPS"]["SerialPath"].as<std::string>("");
|
std::string serialPath = yamlConfig["GPS"]["SerialPath"].as<std::string>("");
|
||||||
if (serialPath != "") {
|
if (serialPath != "") {
|
||||||
Serial1.setPath(serialPath);
|
Serial1.setPath(serialPath);
|
||||||
settingsMap[has_gps] = 1;
|
portduino_config.has_gps = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["I2C"]) {
|
if (yamlConfig["I2C"]) {
|
||||||
settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
portduino_config.i2cdev = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
||||||
}
|
}
|
||||||
if (yamlConfig["Display"]) {
|
if (yamlConfig["Display"]) {
|
||||||
if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789")
|
|
||||||
settingsMap[displayPanel] = st7789;
|
for (auto &screen_name : portduino_config.screen_names) {
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735")
|
if (yamlConfig["Display"]["Panel"].as<std::string>("") == screen_name.second)
|
||||||
settingsMap[displayPanel] = st7735;
|
portduino_config.displayPanel = screen_name.first;
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
}
|
||||||
settingsMap[displayPanel] = st7735s;
|
portduino_config.displayHeight = yamlConfig["Display"]["Height"].as<int>(0);
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7796")
|
portduino_config.displayWidth = yamlConfig["Display"]["Width"].as<int>(0);
|
||||||
settingsMap[displayPanel] = st7796;
|
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341")
|
readGPIOFromYaml(yamlConfig["Display"]["DC"], portduino_config.displayDC, -1);
|
||||||
settingsMap[displayPanel] = ili9341;
|
readGPIOFromYaml(yamlConfig["Display"]["CS"], portduino_config.displayCS, -1);
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9342")
|
readGPIOFromYaml(yamlConfig["Display"]["Backlight"], portduino_config.displayBacklight, -1);
|
||||||
settingsMap[displayPanel] = ili9342;
|
readGPIOFromYaml(yamlConfig["Display"]["BacklightPWMChannel"], portduino_config.displayBacklightPWMChannel, -1);
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9486")
|
readGPIOFromYaml(yamlConfig["Display"]["Reset"], portduino_config.displayReset, -1);
|
||||||
settingsMap[displayPanel] = ili9486;
|
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9488")
|
portduino_config.displayBacklightInvert = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
|
||||||
settingsMap[displayPanel] = ili9488;
|
portduino_config.displayRGBOrder = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "HX8357D")
|
portduino_config.displayOffsetX = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
||||||
settingsMap[displayPanel] = hx8357d;
|
portduino_config.displayOffsetY = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "X11")
|
portduino_config.displayRotate = yamlConfig["Display"]["Rotate"].as<bool>(false);
|
||||||
settingsMap[displayPanel] = x11;
|
portduino_config.displayOffsetRotate = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "FB")
|
portduino_config.displayInvert = yamlConfig["Display"]["Invert"].as<bool>(false);
|
||||||
settingsMap[displayPanel] = fb;
|
portduino_config.displayBusFrequency = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
|
||||||
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
|
|
||||||
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
|
||||||
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
|
||||||
settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1);
|
|
||||||
settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
|
|
||||||
settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1);
|
|
||||||
settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
|
|
||||||
settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as<int>(-1);
|
|
||||||
settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as<int>(-1);
|
|
||||||
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
|
||||||
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
|
||||||
settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
|
|
||||||
settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
|
|
||||||
settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
|
|
||||||
settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
|
|
||||||
if (yamlConfig["Display"]["spidev"]) {
|
if (yamlConfig["Display"]["spidev"]) {
|
||||||
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
portduino_config.display_spi_dev = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
||||||
if (settingsStrings[displayspidev].length() == 14) {
|
if (portduino_config.display_spi_dev.length() == 14) {
|
||||||
int x = settingsStrings[displayspidev].at(11) - '0';
|
int x = portduino_config.display_spi_dev.at(11) - '0';
|
||||||
int y = settingsStrings[displayspidev].at(13) - '0';
|
int y = portduino_config.display_spi_dev.at(13) - '0';
|
||||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||||
settingsMap[displayspidev] = x + y << 4;
|
portduino_config.display_spi_dev_int = x + y << 4;
|
||||||
settingsMap[touchscreenspidev] = settingsMap[displayspidev];
|
portduino_config.touchscreen_spi_dev_int = portduino_config.display_spi_dev_int;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["Touchscreen"]) {
|
if (yamlConfig["Touchscreen"]) {
|
||||||
if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046")
|
if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046")
|
||||||
settingsMap[touchscreenModule] = xpt2046;
|
portduino_config.touchscreenModule = xpt2046;
|
||||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
||||||
settingsMap[touchscreenModule] = stmpe610;
|
portduino_config.touchscreenModule = stmpe610;
|
||||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911")
|
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911")
|
||||||
settingsMap[touchscreenModule] = gt911;
|
portduino_config.touchscreenModule = gt911;
|
||||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06")
|
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06")
|
||||||
settingsMap[touchscreenModule] = ft5x06;
|
portduino_config.touchscreenModule = ft5x06;
|
||||||
settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
|
|
||||||
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as<int>(-1);
|
readGPIOFromYaml(yamlConfig["Touchscreen"]["CS"], portduino_config.touchscreenCS, -1);
|
||||||
settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000);
|
readGPIOFromYaml(yamlConfig["Touchscreen"]["IRQ"], portduino_config.touchscreenIRQ, -1);
|
||||||
settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
|
|
||||||
settingsMap[touchscreenI2CAddr] = yamlConfig["Touchscreen"]["I2CAddr"].as<int>(-1);
|
portduino_config.touchscreenBusFrequency = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000);
|
||||||
|
portduino_config.touchscreenRotate = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
|
||||||
|
portduino_config.touchscreenI2CAddr = yamlConfig["Touchscreen"]["I2CAddr"].as<int>(-1);
|
||||||
if (yamlConfig["Touchscreen"]["spidev"]) {
|
if (yamlConfig["Touchscreen"]["spidev"]) {
|
||||||
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
portduino_config.touchscreen_spi_dev = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
||||||
if (settingsStrings[touchscreenspidev].length() == 14) {
|
if (portduino_config.touchscreen_spi_dev.length() == 14) {
|
||||||
int x = settingsStrings[touchscreenspidev].at(11) - '0';
|
int x = portduino_config.touchscreen_spi_dev.at(11) - '0';
|
||||||
int y = settingsStrings[touchscreenspidev].at(13) - '0';
|
int y = portduino_config.touchscreen_spi_dev.at(13) - '0';
|
||||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||||
settingsMap[touchscreenspidev] = x + y << 4;
|
portduino_config.touchscreen_spi_dev_int = x + y << 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["Input"]) {
|
if (yamlConfig["Input"]) {
|
||||||
settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as<std::string>("");
|
portduino_config.keyboardDevice = (yamlConfig["Input"]["KeyboardDevice"]).as<std::string>("");
|
||||||
settingsStrings[pointerDevice] = (yamlConfig["Input"]["PointerDevice"]).as<std::string>("");
|
portduino_config.pointerDevice = (yamlConfig["Input"]["PointerDevice"]).as<std::string>("");
|
||||||
settingsMap[userButtonPin] = yamlConfig["Input"]["User"].as<int>(RADIOLIB_NC);
|
|
||||||
settingsMap[tbUpPin] = yamlConfig["Input"]["TrackballUp"].as<int>(RADIOLIB_NC);
|
readGPIOFromYaml(yamlConfig["Input"]["User"], portduino_config.userButtonPin);
|
||||||
settingsMap[tbDownPin] = yamlConfig["Input"]["TrackballDown"].as<int>(RADIOLIB_NC);
|
readGPIOFromYaml(yamlConfig["Input"]["TrackballUp"], portduino_config.tbUpPin);
|
||||||
settingsMap[tbLeftPin] = yamlConfig["Input"]["TrackballLeft"].as<int>(RADIOLIB_NC);
|
readGPIOFromYaml(yamlConfig["Input"]["TrackballDown"], portduino_config.tbDownPin);
|
||||||
settingsMap[tbRightPin] = yamlConfig["Input"]["TrackballRight"].as<int>(RADIOLIB_NC);
|
readGPIOFromYaml(yamlConfig["Input"]["TrackballLeft"], portduino_config.tbLeftPin);
|
||||||
settingsMap[tbPressPin] = yamlConfig["Input"]["TrackballPress"].as<int>(RADIOLIB_NC);
|
readGPIOFromYaml(yamlConfig["Input"]["TrackballRight"], portduino_config.tbRightPin);
|
||||||
|
readGPIOFromYaml(yamlConfig["Input"]["TrackballPress"], portduino_config.tbPressPin);
|
||||||
|
|
||||||
if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "RISING") {
|
if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "RISING") {
|
||||||
settingsMap[tbDirection] = 4;
|
portduino_config.tbDirection = 4;
|
||||||
} else if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "FALLING") {
|
} else if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "FALLING") {
|
||||||
settingsMap[tbDirection] = 3;
|
portduino_config.tbDirection = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlConfig["Webserver"]) {
|
if (yamlConfig["Webserver"]) {
|
||||||
settingsMap[webserverport] = (yamlConfig["Webserver"]["Port"]).as<int>(-1);
|
portduino_config.webserverport = (yamlConfig["Webserver"]["Port"]).as<int>(-1);
|
||||||
settingsStrings[webserverrootpath] =
|
portduino_config.webserver_root_path =
|
||||||
(yamlConfig["Webserver"]["RootPath"]).as<std::string>("/usr/share/meshtasticd/web");
|
(yamlConfig["Webserver"]["RootPath"]).as<std::string>("/usr/share/meshtasticd/web");
|
||||||
settingsStrings[websslkeypath] =
|
portduino_config.webserver_ssl_key_path =
|
||||||
(yamlConfig["Webserver"]["SSLKey"]).as<std::string>("/etc/meshtasticd/ssl/private_key.pem");
|
(yamlConfig["Webserver"]["SSLKey"]).as<std::string>("/etc/meshtasticd/ssl/private_key.pem");
|
||||||
settingsStrings[websslcertpath] =
|
portduino_config.webserver_ssl_cert_path =
|
||||||
(yamlConfig["Webserver"]["SSLCert"]).as<std::string>("/etc/meshtasticd/ssl/certificate.pem");
|
(yamlConfig["Webserver"]["SSLCert"]).as<std::string>("/etc/meshtasticd/ssl/certificate.pem");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlConfig["HostMetrics"]) {
|
if (yamlConfig["HostMetrics"]) {
|
||||||
settingsMap[hostMetrics_channel] = (yamlConfig["HostMetrics"]["Channel"]).as<int>(0);
|
portduino_config.hostMetrics_channel = (yamlConfig["HostMetrics"]["Channel"]).as<int>(0);
|
||||||
settingsMap[hostMetrics_interval] = (yamlConfig["HostMetrics"]["ReportInterval"]).as<int>(0);
|
portduino_config.hostMetrics_interval = (yamlConfig["HostMetrics"]["ReportInterval"]).as<int>(0);
|
||||||
settingsStrings[hostMetrics_user_command] = (yamlConfig["HostMetrics"]["UserStringCommand"]).as<std::string>("");
|
portduino_config.hostMetrics_user_command = (yamlConfig["HostMetrics"]["UserStringCommand"]).as<std::string>("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlConfig["Config"]) {
|
if (yamlConfig["Config"]) {
|
||||||
if (yamlConfig["Config"]["DisplayMode"]) {
|
if (yamlConfig["Config"]["DisplayMode"]) {
|
||||||
settingsMap[has_configDisplayMode] = true;
|
portduino_config.has_configDisplayMode = true;
|
||||||
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
|
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
|
||||||
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR;
|
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR;
|
||||||
} else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "INVERTED") {
|
} else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "INVERTED") {
|
||||||
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_INVERTED;
|
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_INVERTED;
|
||||||
} else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "COLOR") {
|
} else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "COLOR") {
|
||||||
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_COLOR;
|
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_COLOR;
|
||||||
} else {
|
} else {
|
||||||
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
|
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlConfig["General"]) {
|
if (yamlConfig["General"]) {
|
||||||
settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
portduino_config.MaxNodes = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||||
settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
portduino_config.maxtophone = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||||
settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as<std::string>("");
|
portduino_config.config_directory = (yamlConfig["General"]["ConfigDirectory"]).as<std::string>("");
|
||||||
settingsStrings[available_directory] =
|
portduino_config.available_directory =
|
||||||
(yamlConfig["General"]["AvailableDirectory"]).as<std::string>("/etc/meshtasticd/available.d/");
|
(yamlConfig["General"]["AvailableDirectory"]).as<std::string>("/etc/meshtasticd/available.d/");
|
||||||
if ((yamlConfig["General"]["MACAddress"]).as<std::string>("") != "" &&
|
if ((yamlConfig["General"]["MACAddress"]).as<std::string>("") != "" &&
|
||||||
(yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
|
(yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
|
||||||
std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl;
|
std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
settingsStrings[mac_address] = (yamlConfig["General"]["MACAddress"]).as<std::string>("");
|
portduino_config.mac_address = (yamlConfig["General"]["MACAddress"]).as<std::string>("");
|
||||||
if ((yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
|
if (portduino_config.mac_address != "") {
|
||||||
std::ifstream infile("/sys/class/net/" + (yamlConfig["General"]["MACAddressSource"]).as<std::string>("") +
|
portduino_config.mac_address_explicit = true;
|
||||||
"/address");
|
} else if ((yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
|
||||||
std::getline(infile, settingsStrings[mac_address]);
|
portduino_config.mac_address_source = (yamlConfig["General"]["MACAddressSource"]).as<std::string>("");
|
||||||
|
std::ifstream infile("/sys/class/net/" + portduino_config.mac_address_source + "/address");
|
||||||
|
std::getline(infile, portduino_config.mac_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/a/20326454
|
// https://stackoverflow.com/a/20326454
|
||||||
settingsStrings[mac_address].erase(
|
portduino_config.mac_address.erase(
|
||||||
std::remove(settingsStrings[mac_address].begin(), settingsStrings[mac_address].end(), ':'),
|
std::remove(portduino_config.mac_address.begin(), portduino_config.mac_address.end(), ':'),
|
||||||
settingsStrings[mac_address].end());
|
portduino_config.mac_address.end());
|
||||||
}
|
}
|
||||||
} catch (YAML::Exception &e) {
|
} catch (YAML::Exception &e) {
|
||||||
std::cout << "*** Exception " << e.what() << std::endl;
|
std::cout << "*** Exception " << e.what() << std::endl;
|
||||||
@@ -851,12 +730,12 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac)
|
|||||||
{
|
{
|
||||||
mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end());
|
mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end());
|
||||||
if (mac_str.length() == 12) {
|
if (mac_str.length() == 12) {
|
||||||
dmac[0] = std::stoi(settingsStrings[mac_address].substr(0, 2), nullptr, 16);
|
dmac[0] = std::stoi(portduino_config.mac_address.substr(0, 2), nullptr, 16);
|
||||||
dmac[1] = std::stoi(settingsStrings[mac_address].substr(2, 2), nullptr, 16);
|
dmac[1] = std::stoi(portduino_config.mac_address.substr(2, 2), nullptr, 16);
|
||||||
dmac[2] = std::stoi(settingsStrings[mac_address].substr(4, 2), nullptr, 16);
|
dmac[2] = std::stoi(portduino_config.mac_address.substr(4, 2), nullptr, 16);
|
||||||
dmac[3] = std::stoi(settingsStrings[mac_address].substr(6, 2), nullptr, 16);
|
dmac[3] = std::stoi(portduino_config.mac_address.substr(6, 2), nullptr, 16);
|
||||||
dmac[4] = std::stoi(settingsStrings[mac_address].substr(8, 2), nullptr, 16);
|
dmac[4] = std::stoi(portduino_config.mac_address.substr(8, 2), nullptr, 16);
|
||||||
dmac[5] = std::stoi(settingsStrings[mac_address].substr(10, 2), nullptr, 16);
|
dmac[5] = std::stoi(portduino_config.mac_address.substr(10, 2), nullptr, 16);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -876,3 +755,18 @@ std::string exec(const char *cmd)
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void readGPIOFromYaml(YAML::Node sourceNode, pinMapping &destPin, int pinDefault)
|
||||||
|
{
|
||||||
|
if (sourceNode.IsMap()) {
|
||||||
|
destPin.enabled = true;
|
||||||
|
destPin.pin = sourceNode["pin"].as<int>(pinDefault);
|
||||||
|
destPin.line = sourceNode["line"].as<int>(destPin.pin);
|
||||||
|
destPin.gpiochip = sourceNode["gpiochip"].as<int>(portduino_config.lora_default_gpiochip);
|
||||||
|
} else if (sourceNode) { // backwards API compatibility
|
||||||
|
destPin.enabled = true;
|
||||||
|
destPin.pin = sourceNode.as<int>(pinDefault);
|
||||||
|
destPin.line = destPin.pin;
|
||||||
|
destPin.gpiochip = portduino_config.lora_default_gpiochip;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "LR11x0Interface.h"
|
#include "LR11x0Interface.h"
|
||||||
#include "Module.h"
|
#include "Module.h"
|
||||||
#include "platform/portduino/USBHal.h"
|
#include "platform/portduino/USBHal.h"
|
||||||
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
// Product strings for auto-configuration
|
// Product strings for auto-configuration
|
||||||
// {"PRODUCT_STRING", "CONFIG.YAML"}
|
// {"PRODUCT_STRING", "CONFIG.YAML"}
|
||||||
@@ -19,36 +20,10 @@ inline const std::unordered_map<std::string, std::string> configProducts = {
|
|||||||
{"RAK6421-13300-S1", "lora-RAK6421-13300-slot1.yaml"},
|
{"RAK6421-13300-S1", "lora-RAK6421-13300-slot1.yaml"},
|
||||||
{"RAK6421-13300-S2", "lora-RAK6421-13300-slot2.yaml"}};
|
{"RAK6421-13300-S2", "lora-RAK6421-13300-slot2.yaml"}};
|
||||||
|
|
||||||
enum configNames {
|
enum screen_modules { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d };
|
||||||
default_gpiochip,
|
enum touchscreen_modules { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
||||||
cs_pin,
|
enum portduino_log_level { level_error, level_warn, level_info, level_debug, level_trace };
|
||||||
cs_line,
|
enum lora_module_enum {
|
||||||
cs_gpiochip,
|
|
||||||
irq_pin,
|
|
||||||
irq_line,
|
|
||||||
irq_gpiochip,
|
|
||||||
busy_pin,
|
|
||||||
busy_line,
|
|
||||||
busy_gpiochip,
|
|
||||||
reset_pin,
|
|
||||||
reset_line,
|
|
||||||
reset_gpiochip,
|
|
||||||
txen_pin,
|
|
||||||
txen_line,
|
|
||||||
txen_gpiochip,
|
|
||||||
rxen_pin,
|
|
||||||
rxen_line,
|
|
||||||
rxen_gpiochip,
|
|
||||||
sx126x_ant_sw_pin,
|
|
||||||
sx126x_ant_sw_line,
|
|
||||||
sx126x_ant_sw_gpiochip,
|
|
||||||
sx126x_max_power,
|
|
||||||
sx128x_max_power,
|
|
||||||
lr1110_max_power,
|
|
||||||
lr1120_max_power,
|
|
||||||
rf95_max_power,
|
|
||||||
dio2_as_rf_switch,
|
|
||||||
dio3_tcxo_voltage,
|
|
||||||
use_simradio,
|
use_simradio,
|
||||||
use_autoconf,
|
use_autoconf,
|
||||||
use_rf95,
|
use_rf95,
|
||||||
@@ -58,72 +33,18 @@ enum configNames {
|
|||||||
use_lr1110,
|
use_lr1110,
|
||||||
use_lr1120,
|
use_lr1120,
|
||||||
use_lr1121,
|
use_lr1121,
|
||||||
use_llcc68,
|
use_llcc68
|
||||||
lora_usb_serial_num,
|
};
|
||||||
lora_usb_pid,
|
|
||||||
lora_usb_vid,
|
struct pinMapping {
|
||||||
userButtonPin,
|
std::string config_section;
|
||||||
tbUpPin,
|
std::string config_name;
|
||||||
tbDownPin,
|
int pin = RADIOLIB_NC;
|
||||||
tbLeftPin,
|
int gpiochip;
|
||||||
tbRightPin,
|
int line;
|
||||||
tbPressPin,
|
bool enabled = false;
|
||||||
tbDirection,
|
|
||||||
spidev,
|
|
||||||
spiSpeed,
|
|
||||||
i2cdev,
|
|
||||||
has_gps,
|
|
||||||
touchscreenModule,
|
|
||||||
touchscreenCS,
|
|
||||||
touchscreenIRQ,
|
|
||||||
touchscreenI2CAddr,
|
|
||||||
touchscreenBusFrequency,
|
|
||||||
touchscreenRotate,
|
|
||||||
touchscreenspidev,
|
|
||||||
displayspidev,
|
|
||||||
displayBusFrequency,
|
|
||||||
displayPanel,
|
|
||||||
displayWidth,
|
|
||||||
displayHeight,
|
|
||||||
displayCS,
|
|
||||||
displayDC,
|
|
||||||
displayRGBOrder,
|
|
||||||
displayBacklight,
|
|
||||||
displayBacklightPWMChannel,
|
|
||||||
displayBacklightInvert,
|
|
||||||
displayReset,
|
|
||||||
displayRotate,
|
|
||||||
displayOffsetRotate,
|
|
||||||
displayOffsetX,
|
|
||||||
displayOffsetY,
|
|
||||||
displayInvert,
|
|
||||||
keyboardDevice,
|
|
||||||
pointerDevice,
|
|
||||||
logoutputlevel,
|
|
||||||
traceFilename,
|
|
||||||
webserver,
|
|
||||||
webserverport,
|
|
||||||
webserverrootpath,
|
|
||||||
websslkeypath,
|
|
||||||
websslcertpath,
|
|
||||||
maxtophone,
|
|
||||||
maxnodes,
|
|
||||||
ascii_logs,
|
|
||||||
config_directory,
|
|
||||||
available_directory,
|
|
||||||
mac_address,
|
|
||||||
hostMetrics_interval,
|
|
||||||
hostMetrics_channel,
|
|
||||||
hostMetrics_user_command,
|
|
||||||
configDisplayMode,
|
|
||||||
has_configDisplayMode
|
|
||||||
};
|
};
|
||||||
enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d };
|
|
||||||
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
|
||||||
enum { level_error, level_warn, level_info, level_debug, level_trace };
|
|
||||||
|
|
||||||
extern std::map<configNames, int> settingsMap;
|
|
||||||
extern std::map<configNames, std::string> settingsStrings;
|
|
||||||
extern std::ofstream traceFile;
|
extern std::ofstream traceFile;
|
||||||
extern Ch341Hal *ch341Hal;
|
extern Ch341Hal *ch341Hal;
|
||||||
int initGPIOPin(int pinNum, std::string gpioChipname, int line);
|
int initGPIOPin(int pinNum, std::string gpioChipname, int line);
|
||||||
@@ -131,13 +52,422 @@ bool loadConfig(const char *configPath);
|
|||||||
static bool ends_with(std::string_view str, std::string_view suffix);
|
static bool ends_with(std::string_view str, std::string_view suffix);
|
||||||
void getMacAddr(uint8_t *dmac);
|
void getMacAddr(uint8_t *dmac);
|
||||||
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
|
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
|
||||||
|
void readGPIOFromYaml(YAML::Node sourceNode, pinMapping &destPin, int pinDefault = RADIOLIB_NC);
|
||||||
std::string exec(const char *cmd);
|
std::string exec(const char *cmd);
|
||||||
|
|
||||||
extern struct portduino_config_struct {
|
extern struct portduino_config_struct {
|
||||||
|
// Lora
|
||||||
|
std::map<lora_module_enum, std::string> loraModules = {
|
||||||
|
{use_simradio, "sim"}, {use_autoconf, "auto"}, {use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"},
|
||||||
|
{use_sx1280, "sx1280"}, {use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
||||||
|
|
||||||
|
std::map<screen_modules, std::string> screen_names = {{x11, "X11"}, {fb, "FB"}, {st7789, "ST7789"},
|
||||||
|
{st7735, "ST7735"}, {st7735s, "ST7735S"}, {st7796, "ST7796"},
|
||||||
|
{ili9341, "ILI9341"}, {ili9342, "ILI9342"}, {ili9486, "ILI9486"},
|
||||||
|
{ili9488, "ILI9488"}, {hx8357d, "HX8357D"}};
|
||||||
|
|
||||||
|
lora_module_enum lora_module;
|
||||||
bool has_rfswitch_table = false;
|
bool has_rfswitch_table = false;
|
||||||
uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
|
uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
|
||||||
Module::RfSwitchMode_t rfswitch_table[8];
|
Module::RfSwitchMode_t rfswitch_table[8];
|
||||||
bool force_simradio = false;
|
bool force_simradio = false;
|
||||||
bool has_device_id = false;
|
bool has_device_id = false;
|
||||||
uint8_t device_id[16] = {0};
|
uint8_t device_id[16] = {0};
|
||||||
|
std::string lora_spi_dev = "";
|
||||||
|
std::string lora_usb_serial_num = "";
|
||||||
|
int lora_spi_dev_int = 0;
|
||||||
|
int lora_default_gpiochip = 0;
|
||||||
|
int sx126x_max_power = 22;
|
||||||
|
int sx128x_max_power = 13;
|
||||||
|
int lr1110_max_power = 22;
|
||||||
|
int lr1120_max_power = 13;
|
||||||
|
int rf95_max_power = 20;
|
||||||
|
bool dio2_as_rf_switch = false;
|
||||||
|
int dio3_tcxo_voltage = 0;
|
||||||
|
int lora_usb_pid = 0x5512;
|
||||||
|
int lora_usb_vid = 0x1A86;
|
||||||
|
int spiSpeed = 2000000;
|
||||||
|
pinMapping lora_cs_pin = {"Lora", "CS"};
|
||||||
|
pinMapping lora_irq_pin = {"Lora", "IRQ"};
|
||||||
|
pinMapping lora_busy_pin = {"Lora", "Busy"};
|
||||||
|
pinMapping lora_reset_pin = {"Lora", "Reset"};
|
||||||
|
pinMapping lora_txen_pin = {"Lora", "TXen"};
|
||||||
|
pinMapping lora_rxen_pin = {"Lora", "RXen"};
|
||||||
|
pinMapping lora_sx126x_ant_sw_pin = {"Lora", "SX126X_ANT_SW"};
|
||||||
|
|
||||||
|
// GPS
|
||||||
|
bool has_gps = false;
|
||||||
|
|
||||||
|
// I2C
|
||||||
|
std::string i2cdev = "";
|
||||||
|
|
||||||
|
// Display
|
||||||
|
std::string display_spi_dev = "";
|
||||||
|
int display_spi_dev_int = 0;
|
||||||
|
int displayBusFrequency = 40000000;
|
||||||
|
screen_modules displayPanel = no_screen;
|
||||||
|
int displayWidth = 0;
|
||||||
|
int displayHeight = 0;
|
||||||
|
bool displayRGBOrder = false;
|
||||||
|
bool displayBacklightInvert = false;
|
||||||
|
bool displayRotate = false;
|
||||||
|
int displayOffsetRotate = 1;
|
||||||
|
bool displayInvert = false;
|
||||||
|
int displayOffsetX = 0;
|
||||||
|
int displayOffsetY = 0;
|
||||||
|
pinMapping displayDC = {"Display", "DC"};
|
||||||
|
pinMapping displayCS = {"Display", "CS"};
|
||||||
|
pinMapping displayBacklight = {"Display", "Backlight"};
|
||||||
|
pinMapping displayBacklightPWMChannel = {"Display", "BacklightPWMChannel"};
|
||||||
|
pinMapping displayReset = {"Display", "Reset"};
|
||||||
|
|
||||||
|
// Touchscreen
|
||||||
|
std::string touchscreen_spi_dev = "";
|
||||||
|
int touchscreen_spi_dev_int = 0;
|
||||||
|
touchscreen_modules touchscreenModule = no_touchscreen;
|
||||||
|
int touchscreenI2CAddr = -1;
|
||||||
|
int touchscreenBusFrequency = 1000000;
|
||||||
|
int touchscreenRotate = -1;
|
||||||
|
pinMapping touchscreenCS = {"Touchscreen", "CS"};
|
||||||
|
pinMapping touchscreenIRQ = {"Touchscreen", "IRQ"};
|
||||||
|
|
||||||
|
// Input
|
||||||
|
std::string keyboardDevice = "";
|
||||||
|
std::string pointerDevice = "";
|
||||||
|
int tbDirection;
|
||||||
|
pinMapping userButtonPin = {"Input", "User"};
|
||||||
|
pinMapping tbUpPin = {"Input", "TrackballUp"};
|
||||||
|
pinMapping tbDownPin = {"Input", "TrackballDown"};
|
||||||
|
pinMapping tbLeftPin = {"Input", "TrackballLwft"};
|
||||||
|
pinMapping tbRightPin = {"Input", "TrackballRight"};
|
||||||
|
pinMapping tbPressPin = {"Input", "TrackballPress"};
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
portduino_log_level logoutputlevel = level_debug;
|
||||||
|
std::string traceFilename;
|
||||||
|
bool ascii_logs = !isatty(1);
|
||||||
|
bool ascii_logs_explicit = false;
|
||||||
|
|
||||||
|
// Webserver
|
||||||
|
std::string webserver_root_path = "";
|
||||||
|
std::string webserver_ssl_key_path = "/etc/meshtasticd/ssl/private_key.pem";
|
||||||
|
std::string webserver_ssl_cert_path = "/etc/meshtasticd/ssl/certificate.pem";
|
||||||
|
int webserverport = -1;
|
||||||
|
|
||||||
|
// HostMetrics
|
||||||
|
std::string hostMetrics_user_command = "";
|
||||||
|
int hostMetrics_interval = 0;
|
||||||
|
int hostMetrics_channel = 0;
|
||||||
|
|
||||||
|
// config
|
||||||
|
int configDisplayMode = 0;
|
||||||
|
bool has_configDisplayMode = false;
|
||||||
|
|
||||||
|
// General
|
||||||
|
std::string mac_address = "";
|
||||||
|
bool mac_address_explicit = false;
|
||||||
|
std::string mac_address_source = "";
|
||||||
|
std::string config_directory = "";
|
||||||
|
std::string available_directory = "/etc/meshtasticd/available.d/";
|
||||||
|
int maxtophone = 100;
|
||||||
|
int MaxNodes = 200;
|
||||||
|
|
||||||
|
pinMapping *all_pins[20] = {&lora_cs_pin,
|
||||||
|
&lora_irq_pin,
|
||||||
|
&lora_busy_pin,
|
||||||
|
&lora_reset_pin,
|
||||||
|
&lora_txen_pin,
|
||||||
|
&lora_rxen_pin,
|
||||||
|
&lora_sx126x_ant_sw_pin,
|
||||||
|
&displayDC,
|
||||||
|
&displayCS,
|
||||||
|
&displayBacklight,
|
||||||
|
&displayBacklightPWMChannel,
|
||||||
|
&displayReset,
|
||||||
|
&touchscreenCS,
|
||||||
|
&touchscreenIRQ,
|
||||||
|
&userButtonPin,
|
||||||
|
&tbUpPin,
|
||||||
|
&tbDownPin,
|
||||||
|
&tbLeftPin,
|
||||||
|
&tbRightPin,
|
||||||
|
&tbPressPin};
|
||||||
|
|
||||||
|
std::string emit_yaml()
|
||||||
|
{
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
|
||||||
|
// Lora
|
||||||
|
out << YAML::Key << "Lora" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "Module" << YAML::Value << loraModules[lora_module];
|
||||||
|
|
||||||
|
for (auto lora_pin : all_pins) {
|
||||||
|
if (lora_pin->config_section == "Lora" && lora_pin->enabled) {
|
||||||
|
out << YAML::Key << lora_pin->config_name << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "pin" << YAML::Value << lora_pin->pin;
|
||||||
|
out << YAML::Key << "line" << YAML::Value << lora_pin->line;
|
||||||
|
out << YAML::Key << "gpiochip" << YAML::Value << lora_pin->gpiochip;
|
||||||
|
out << YAML::EndMap; // User
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sx126x_max_power != 22)
|
||||||
|
out << YAML::Key << "SX126X_MAX_POWER" << YAML::Value << sx126x_max_power;
|
||||||
|
if (sx128x_max_power != 13)
|
||||||
|
out << YAML::Key << "SX128X_MAX_POWER" << YAML::Value << sx128x_max_power;
|
||||||
|
if (lr1110_max_power != 22)
|
||||||
|
out << YAML::Key << "LR1110_MAX_POWER" << YAML::Value << lr1110_max_power;
|
||||||
|
if (lr1120_max_power != 13)
|
||||||
|
out << YAML::Key << "LR1120_MAX_POWER" << YAML::Value << lr1120_max_power;
|
||||||
|
if (rf95_max_power != 20)
|
||||||
|
out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power;
|
||||||
|
out << YAML::Key << "DIO2_AS_RF_SWITCH" << YAML::Value << dio2_as_rf_switch;
|
||||||
|
if (dio3_tcxo_voltage != 0)
|
||||||
|
out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << dio3_tcxo_voltage;
|
||||||
|
if (lora_usb_pid != 0x5512)
|
||||||
|
out << YAML::Key << "USB_PID" << YAML::Value << YAML::Hex << lora_usb_pid;
|
||||||
|
if (lora_usb_vid != 0x1A86)
|
||||||
|
out << YAML::Key << "USB_VID" << YAML::Value << YAML::Hex << lora_usb_vid;
|
||||||
|
if (lora_spi_dev != "")
|
||||||
|
out << YAML::Key << "spidev" << YAML::Value << lora_spi_dev;
|
||||||
|
if (lora_usb_serial_num != "")
|
||||||
|
out << YAML::Key << "USB_Serialnum" << YAML::Value << lora_usb_serial_num;
|
||||||
|
out << YAML::Key << "spiSpeed" << YAML::Value << spiSpeed;
|
||||||
|
if (rfswitch_dio_pins[0] != RADIOLIB_NC) {
|
||||||
|
out << YAML::Key << "rfswitch_table" << YAML::Value << YAML::BeginMap;
|
||||||
|
|
||||||
|
out << YAML::Key << "pins";
|
||||||
|
out << YAML::Value << YAML::Flow << YAML::BeginSeq;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
// set up the pin array first
|
||||||
|
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO5)
|
||||||
|
out << "DIO5";
|
||||||
|
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO6)
|
||||||
|
out << "DIO6";
|
||||||
|
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO7)
|
||||||
|
out << "DIO7";
|
||||||
|
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO8)
|
||||||
|
out << "DIO8";
|
||||||
|
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO10)
|
||||||
|
out << "DIO10";
|
||||||
|
}
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
out << YAML::Key << "MODE_STBY";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
out << YAML::Key << "MODE_RX";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
out << YAML::Key << "MODE_TX";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
out << YAML::Key << "MODE_TX_HP";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
out << YAML::Key << "MODE_TX_HF";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
out << YAML::Key << "MODE_GNSS";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
out << YAML::Key << "MODE_WIFI";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << YAML::Value << YAML::Flow << YAML::BeginSeq;
|
||||||
|
for (int j = 0; j < 5; j++) {
|
||||||
|
if (rfswitch_table[i].values[j] == HIGH) {
|
||||||
|
out << "HIGH";
|
||||||
|
} else {
|
||||||
|
out << "LOW";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
}
|
||||||
|
out << YAML::EndMap; // rfswitch_table
|
||||||
|
}
|
||||||
|
out << YAML::EndMap; // Lora
|
||||||
|
|
||||||
|
if (i2cdev != "") {
|
||||||
|
out << YAML::Key << "I2C" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "I2CDevice" << YAML::Value << i2cdev;
|
||||||
|
out << YAML::EndMap; // I2C
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display
|
||||||
|
if (displayPanel != no_screen) {
|
||||||
|
out << YAML::Key << "Display" << YAML::Value << YAML::BeginMap;
|
||||||
|
for (auto &screen_name : screen_names) {
|
||||||
|
if (displayPanel == screen_name.first)
|
||||||
|
out << YAML::Key << "Module" << YAML::Value << screen_name.second;
|
||||||
|
}
|
||||||
|
for (auto display_pin : all_pins) {
|
||||||
|
if (display_pin->config_section == "Display" && display_pin->enabled) {
|
||||||
|
out << YAML::Key << display_pin->config_name << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "pin" << YAML::Value << display_pin->pin;
|
||||||
|
out << YAML::Key << "line" << YAML::Value << display_pin->line;
|
||||||
|
out << YAML::Key << "gpiochip" << YAML::Value << display_pin->gpiochip;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << YAML::Key << "spidev" << YAML::Value << display_spi_dev;
|
||||||
|
out << YAML::Key << "BusFrequency" << YAML::Value << displayBusFrequency;
|
||||||
|
if (displayWidth)
|
||||||
|
out << YAML::Key << "Width" << YAML::Value << displayWidth;
|
||||||
|
if (displayHeight)
|
||||||
|
out << YAML::Key << "Height" << YAML::Value << displayHeight;
|
||||||
|
if (displayRGBOrder)
|
||||||
|
out << YAML::Key << "RGBOrder" << YAML::Value << true;
|
||||||
|
if (displayBacklightInvert)
|
||||||
|
out << YAML::Key << "BacklightInvert" << YAML::Value << true;
|
||||||
|
if (displayRotate)
|
||||||
|
out << YAML::Key << "Rotate" << YAML::Value << true;
|
||||||
|
if (displayInvert)
|
||||||
|
out << YAML::Key << "Invert" << YAML::Value << true;
|
||||||
|
if (displayOffsetX)
|
||||||
|
out << YAML::Key << "OffsetX" << YAML::Value << displayOffsetX;
|
||||||
|
if (displayOffsetY)
|
||||||
|
out << YAML::Key << "OffsetY" << YAML::Value << displayOffsetY;
|
||||||
|
|
||||||
|
out << YAML::Key << "OffsetRotate" << YAML::Value << displayOffsetRotate;
|
||||||
|
|
||||||
|
out << YAML::EndMap; // Display
|
||||||
|
}
|
||||||
|
|
||||||
|
// Touchscreen
|
||||||
|
if (touchscreen_spi_dev != "") {
|
||||||
|
out << YAML::Key << "Touchscreen" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "spidev" << YAML::Value << touchscreen_spi_dev;
|
||||||
|
out << YAML::Key << "BusFrequency" << YAML::Value << touchscreenBusFrequency;
|
||||||
|
switch (touchscreenModule) {
|
||||||
|
case xpt2046:
|
||||||
|
out << YAML::Key << "Module" << YAML::Value << "XPT2046";
|
||||||
|
case stmpe610:
|
||||||
|
out << YAML::Key << "Module" << YAML::Value << "STMPE610";
|
||||||
|
case gt911:
|
||||||
|
out << YAML::Key << "Module" << YAML::Value << "GT911";
|
||||||
|
case ft5x06:
|
||||||
|
out << YAML::Key << "Module" << YAML::Value << "FT5x06";
|
||||||
|
}
|
||||||
|
for (auto touchscreen_pin : all_pins) {
|
||||||
|
if (touchscreen_pin->config_section == "Touchscreen" && touchscreen_pin->enabled) {
|
||||||
|
out << YAML::Key << touchscreen_pin->config_name << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "pin" << YAML::Value << touchscreen_pin->pin;
|
||||||
|
out << YAML::Key << "line" << YAML::Value << touchscreen_pin->line;
|
||||||
|
out << YAML::Key << "gpiochip" << YAML::Value << touchscreen_pin->gpiochip;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (touchscreenRotate != -1)
|
||||||
|
out << YAML::Key << "Rotate" << YAML::Value << touchscreenRotate;
|
||||||
|
if (touchscreenI2CAddr != -1)
|
||||||
|
out << YAML::Key << "I2CAddr" << YAML::Value << touchscreenI2CAddr;
|
||||||
|
out << YAML::EndMap; // Touchscreen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input
|
||||||
|
out << YAML::Key << "Input" << YAML::Value << YAML::BeginMap;
|
||||||
|
if (keyboardDevice != "")
|
||||||
|
out << YAML::Key << "KeyboardDevice" << YAML::Value << keyboardDevice;
|
||||||
|
if (pointerDevice != "")
|
||||||
|
out << YAML::Key << "PointerDevice" << YAML::Value << pointerDevice;
|
||||||
|
|
||||||
|
for (auto input_pin : all_pins) {
|
||||||
|
if (input_pin->config_section == "Input" && input_pin->enabled) {
|
||||||
|
out << YAML::Key << input_pin->config_name << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "pin" << YAML::Value << input_pin->pin;
|
||||||
|
out << YAML::Key << "line" << YAML::Value << input_pin->line;
|
||||||
|
out << YAML::Key << "gpiochip" << YAML::Value << input_pin->gpiochip;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tbDirection == 3)
|
||||||
|
out << YAML::Key << "TrackballDirection" << YAML::Value << "FALLING";
|
||||||
|
|
||||||
|
out << YAML::EndMap; // Input
|
||||||
|
|
||||||
|
out << YAML::Key << "Logging" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "LogLevel" << YAML::Value;
|
||||||
|
switch (logoutputlevel) {
|
||||||
|
case level_error:
|
||||||
|
out << "error";
|
||||||
|
break;
|
||||||
|
case level_warn:
|
||||||
|
out << "warn";
|
||||||
|
break;
|
||||||
|
case level_info:
|
||||||
|
out << "info";
|
||||||
|
break;
|
||||||
|
case level_debug:
|
||||||
|
out << "debug";
|
||||||
|
break;
|
||||||
|
case level_trace:
|
||||||
|
out << "trace";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (traceFilename != "")
|
||||||
|
out << YAML::Key << "TraceFile" << YAML::Value << traceFilename;
|
||||||
|
if (ascii_logs_explicit) {
|
||||||
|
out << YAML::Key << "AsciiLogs" << YAML::Value << ascii_logs;
|
||||||
|
}
|
||||||
|
out << YAML::EndMap; // Logging
|
||||||
|
|
||||||
|
// Webserver
|
||||||
|
if (webserver_root_path != "") {
|
||||||
|
out << YAML::Key << "Webserver" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "RootPath" << YAML::Value << webserver_root_path;
|
||||||
|
out << YAML::Key << "SSLKey" << YAML::Value << webserver_ssl_key_path;
|
||||||
|
out << YAML::Key << "SSLCert" << YAML::Value << webserver_ssl_cert_path;
|
||||||
|
out << YAML::Key << "Port" << YAML::Value << webserverport;
|
||||||
|
out << YAML::EndMap; // Webserver
|
||||||
|
}
|
||||||
|
|
||||||
|
// HostMetrics
|
||||||
|
if (hostMetrics_user_command != "") {
|
||||||
|
out << YAML::Key << "HostMetrics" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "UserStringCommand" << YAML::Value << hostMetrics_user_command;
|
||||||
|
out << YAML::Key << "ReportInterval" << YAML::Value << hostMetrics_interval;
|
||||||
|
out << YAML::Key << "Channel" << YAML::Value << hostMetrics_channel;
|
||||||
|
|
||||||
|
out << YAML::EndMap; // HostMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
// config
|
||||||
|
if (has_configDisplayMode) {
|
||||||
|
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
|
||||||
|
switch (configDisplayMode) {
|
||||||
|
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
||||||
|
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
||||||
|
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
||||||
|
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
||||||
|
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
||||||
|
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
||||||
|
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
||||||
|
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << YAML::EndMap; // Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// General
|
||||||
|
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
|
||||||
|
if (config_directory != "")
|
||||||
|
out << YAML::Key << "ConfigDirectory" << YAML::Value << config_directory;
|
||||||
|
if (mac_address_explicit)
|
||||||
|
out << YAML::Key << "MACAddress" << YAML::Value << mac_address;
|
||||||
|
if (mac_address_source != "")
|
||||||
|
out << YAML::Key << "MACAddressSource" << YAML::Value << mac_address_source;
|
||||||
|
if (available_directory != "")
|
||||||
|
out << YAML::Key << "AvailableDirectory" << YAML::Value << available_directory;
|
||||||
|
out << YAML::Key << "MaxMessageQueue" << YAML::Value << maxtophone;
|
||||||
|
out << YAML::Key << "MaxNodes" << YAML::Value << MaxNodes;
|
||||||
|
out << YAML::EndMap; // General
|
||||||
|
return out.c_str();
|
||||||
|
}
|
||||||
} portduino_config;
|
} portduino_config;
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#ifndef HAS_TRACKBALL
|
#ifndef HAS_TRACKBALL
|
||||||
#define HAS_TRACKBALL 1
|
#define HAS_TRACKBALL 1
|
||||||
#define TB_DOWN (uint8_t) settingsMap[tbDownPin]
|
#define TB_DOWN (uint8_t) portduino_config.tbDownPin.pin
|
||||||
#define TB_UP (uint8_t) settingsMap[tbUpPin]
|
#define TB_UP (uint8_t) portduino_config.tbUpPin.pin
|
||||||
#define TB_LEFT (uint8_t) settingsMap[tbLeftPin]
|
#define TB_LEFT (uint8_t) portduino_config.tbLeftPin.pin
|
||||||
#define TB_RIGHT (uint8_t) settingsMap[tbRightPin]
|
#define TB_RIGHT (uint8_t) portduino_config.tbRightPin.pin
|
||||||
#define TB_PRESS (uint8_t) settingsMap[tbPressPin]
|
#define TB_PRESS (uint8_t) portduino_config.tbPressPin.pin
|
||||||
#endif
|
#endif
|
||||||
@@ -431,15 +431,6 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
|||||||
gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_LOW_LEVEL); // pmu irq
|
gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_LOW_LEVEL); // pmu irq
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef T_LORA_PAGER
|
|
||||||
LOG_DEBUG("power down XL9555 io");
|
|
||||||
io.digitalWrite(EXPANDS_DRV_EN, LOW);
|
|
||||||
io.digitalWrite(EXPANDS_AMP_EN, LOW);
|
|
||||||
io.digitalWrite(EXPANDS_KB_EN, LOW);
|
|
||||||
io.digitalWrite(EXPANDS_SD_EN, LOW);
|
|
||||||
io.digitalWrite(EXPANDS_GPIO_EN, LOW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto res = esp_sleep_enable_gpio_wakeup();
|
auto res = esp_sleep_enable_gpio_wakeup();
|
||||||
if (res != ESP_OK) {
|
if (res != ESP_OK) {
|
||||||
LOG_ERROR("esp_sleep_enable_gpio_wakeup result %d", res);
|
LOG_ERROR("esp_sleep_enable_gpio_wakeup result %d", res);
|
||||||
@@ -480,14 +471,6 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
|||||||
gpio_wakeup_disable((gpio_num_t)RF95_IRQ);
|
gpio_wakeup_disable((gpio_num_t)RF95_IRQ);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef T_LORA_PAGER
|
|
||||||
LOG_DEBUG("power up XL9555 io");
|
|
||||||
io.digitalWrite(EXPANDS_DRV_EN, HIGH);
|
|
||||||
io.digitalWrite(EXPANDS_AMP_EN, HIGH);
|
|
||||||
io.digitalWrite(EXPANDS_KB_EN, HIGH);
|
|
||||||
io.digitalWrite(EXPANDS_SD_EN, HIGH);
|
|
||||||
io.digitalWrite(EXPANDS_GPIO_EN, HIGH);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||||
notifyLightSleepEnd.notifyObservers(cause); // Button interrupts are reattached here
|
notifyLightSleepEnd.notifyObservers(cause); // Button interrupts are reattached here
|
||||||
|
|||||||
@@ -1,30 +1,7 @@
|
|||||||
#include "../test_helpers.h"
|
#include "../test_helpers.h"
|
||||||
|
|
||||||
// test data initialization
|
// Helper function for all encrypted packet assertions
|
||||||
const int from = 0x11223344;
|
void assert_encrypted_packet(const std::string &json, meshtastic_MeshPacket packet)
|
||||||
const int to = 0x55667788;
|
|
||||||
const int id = 0x9999;
|
|
||||||
|
|
||||||
// Helper function to create a test encrypted packet
|
|
||||||
meshtastic_MeshPacket create_test_encrypted_packet(uint32_t from, uint32_t to, uint32_t id, const char *data)
|
|
||||||
{
|
|
||||||
meshtastic_MeshPacket packet = meshtastic_MeshPacket_init_zero;
|
|
||||||
packet.from = from;
|
|
||||||
packet.to = to;
|
|
||||||
packet.id = id;
|
|
||||||
packet.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
packet.encrypted.size = strlen(data);
|
|
||||||
memcpy(packet.encrypted.bytes, data, packet.encrypted.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprehensive helper function for all encrypted packet assertions
|
|
||||||
void assert_encrypted_packet(const std::string &json, uint32_t expected_from, uint32_t expected_to, uint32_t expected_id,
|
|
||||||
size_t expected_size)
|
|
||||||
{
|
{
|
||||||
// Parse and validate JSON
|
// Parse and validate JSON
|
||||||
TEST_ASSERT_TRUE(json.length() > 0);
|
TEST_ASSERT_TRUE(json.length() > 0);
|
||||||
@@ -37,24 +14,24 @@ void assert_encrypted_packet(const std::string &json, uint32_t expected_from, ui
|
|||||||
|
|
||||||
// Assert basic packet fields
|
// Assert basic packet fields
|
||||||
TEST_ASSERT_TRUE(jsonObj.find("from") != jsonObj.end());
|
TEST_ASSERT_TRUE(jsonObj.find("from") != jsonObj.end());
|
||||||
TEST_ASSERT_EQUAL(expected_from, (uint32_t)jsonObj.at("from")->AsNumber());
|
TEST_ASSERT_EQUAL(packet.from, (uint32_t)jsonObj.at("from")->AsNumber());
|
||||||
|
|
||||||
TEST_ASSERT_TRUE(jsonObj.find("to") != jsonObj.end());
|
TEST_ASSERT_TRUE(jsonObj.find("to") != jsonObj.end());
|
||||||
TEST_ASSERT_EQUAL(expected_to, (uint32_t)jsonObj.at("to")->AsNumber());
|
TEST_ASSERT_EQUAL(packet.to, (uint32_t)jsonObj.at("to")->AsNumber());
|
||||||
|
|
||||||
TEST_ASSERT_TRUE(jsonObj.find("id") != jsonObj.end());
|
TEST_ASSERT_TRUE(jsonObj.find("id") != jsonObj.end());
|
||||||
TEST_ASSERT_EQUAL(expected_id, (uint32_t)jsonObj.at("id")->AsNumber());
|
TEST_ASSERT_EQUAL(packet.id, (uint32_t)jsonObj.at("id")->AsNumber());
|
||||||
|
|
||||||
// Assert encrypted data fields
|
// Assert encrypted data fields
|
||||||
TEST_ASSERT_TRUE(jsonObj.find("bytes") != jsonObj.end());
|
TEST_ASSERT_TRUE(jsonObj.find("bytes") != jsonObj.end());
|
||||||
TEST_ASSERT_TRUE(jsonObj.at("bytes")->IsString());
|
TEST_ASSERT_TRUE(jsonObj.at("bytes")->IsString());
|
||||||
|
|
||||||
TEST_ASSERT_TRUE(jsonObj.find("size") != jsonObj.end());
|
TEST_ASSERT_TRUE(jsonObj.find("size") != jsonObj.end());
|
||||||
TEST_ASSERT_EQUAL(expected_size, (int)jsonObj.at("size")->AsNumber());
|
TEST_ASSERT_EQUAL(packet.encrypted.size, (int)jsonObj.at("size")->AsNumber());
|
||||||
|
|
||||||
// Assert hex encoding
|
// Assert hex encoding
|
||||||
std::string encrypted_hex = jsonObj["bytes"]->AsString();
|
std::string encrypted_hex = jsonObj["bytes"]->AsString();
|
||||||
TEST_ASSERT_EQUAL(expected_size * 2, encrypted_hex.length());
|
TEST_ASSERT_EQUAL(packet.encrypted.size * 2, encrypted_hex.length());
|
||||||
|
|
||||||
delete root;
|
delete root;
|
||||||
}
|
}
|
||||||
@@ -63,20 +40,20 @@ void assert_encrypted_packet(const std::string &json, uint32_t expected_from, ui
|
|||||||
void test_encrypted_packet_serialization()
|
void test_encrypted_packet_serialization()
|
||||||
{
|
{
|
||||||
const char *data = "encrypted_payload_data";
|
const char *data = "encrypted_payload_data";
|
||||||
|
meshtastic_MeshPacket packet =
|
||||||
meshtastic_MeshPacket packet = create_test_encrypted_packet(from, to, id, data);
|
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, reinterpret_cast<const uint8_t *>(data), strlen(data),
|
||||||
|
meshtastic_MeshPacket_encrypted_tag);
|
||||||
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
||||||
|
|
||||||
assert_encrypted_packet(json, from, to, id, strlen(data));
|
assert_encrypted_packet(json, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test empty encrypted packet
|
// Test empty encrypted packet
|
||||||
void test_empty_encrypted_packet()
|
void test_empty_encrypted_packet()
|
||||||
{
|
{
|
||||||
const char *data = "";
|
meshtastic_MeshPacket packet =
|
||||||
|
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, nullptr, 0, meshtastic_MeshPacket_encrypted_tag);
|
||||||
meshtastic_MeshPacket packet = create_test_encrypted_packet(from, to, id, data);
|
|
||||||
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
||||||
|
|
||||||
assert_encrypted_packet(json, from, to, id, strlen(data));
|
assert_encrypted_packet(json, packet);
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,8 @@
|
|||||||
#include <unity.h>
|
#include <unity.h>
|
||||||
|
|
||||||
// Helper function to create a test packet with the given port and payload
|
// Helper function to create a test packet with the given port and payload
|
||||||
static meshtastic_MeshPacket create_test_packet(meshtastic_PortNum port, const uint8_t *payload, size_t payload_size)
|
static meshtastic_MeshPacket create_test_packet(meshtastic_PortNum port, const uint8_t *payload, size_t payload_size,
|
||||||
|
int payload_variant = meshtastic_MeshPacket_decoded_tag)
|
||||||
{
|
{
|
||||||
meshtastic_MeshPacket packet = meshtastic_MeshPacket_init_zero;
|
meshtastic_MeshPacket packet = meshtastic_MeshPacket_init_zero;
|
||||||
|
|
||||||
@@ -29,8 +30,12 @@ static meshtastic_MeshPacket create_test_packet(meshtastic_PortNum port, const u
|
|||||||
packet.delayed = meshtastic_MeshPacket_Delayed_NO_DELAY;
|
packet.delayed = meshtastic_MeshPacket_Delayed_NO_DELAY;
|
||||||
|
|
||||||
// Set decoded variant
|
// Set decoded variant
|
||||||
packet.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
packet.which_payload_variant = payload_variant;
|
||||||
packet.decoded.portnum = port;
|
packet.decoded.portnum = port;
|
||||||
|
if (payload_variant == meshtastic_MeshPacket_encrypted_tag && payload) {
|
||||||
|
packet.encrypted.size = payload_size;
|
||||||
|
memcpy(packet.encrypted.bytes, payload, packet.encrypted.size);
|
||||||
|
}
|
||||||
memcpy(packet.decoded.payload.bytes, payload, payload_size);
|
memcpy(packet.decoded.payload.bytes, payload, payload_size);
|
||||||
packet.decoded.payload.size = payload_size;
|
packet.decoded.payload.size = payload_size;
|
||||||
packet.decoded.want_response = false;
|
packet.decoded.want_response = false;
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
; 9M2IBR APRS LoRa Tracker: ESP32-WROOM-32 + EBYTE E22-400M30S
|
||||||
|
; https://shopee.com.my/product/1095224/21692283917
|
||||||
|
[env:9m2ibr_aprs_lora_tracker]
|
||||||
|
extends = esp32_base
|
||||||
|
board = esp32doit-devkit-v1
|
||||||
|
board_level = extra
|
||||||
|
build_flags =
|
||||||
|
${esp32_base.build_flags}
|
||||||
|
-D PRIVATE_HW
|
||||||
|
-D EBYTE_E22
|
||||||
|
-D EBYTE_E22_900M30S ; Assume Tx power curve is identical to 900M30S as there is no documentation
|
||||||
|
-I variants/esp32/diy/9m2ibr_aprs_lora_tracker
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
9M2IBR APRS LoRa Tracker: ESP32-WROOM-32 + EBYTE E22-400M30S
|
||||||
|
https://shopee.com.my/product/1095224/21692283917
|
||||||
|
|
||||||
|
Originally developed for LoRa_APRS_iGate and GPIO is similar to
|
||||||
|
https://github.com/richonguzman/LoRa_APRS_iGate/blob/main/variants/ESP32_DIY_1W_LoRa_Mesh_V1_2/board_pinout.h
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OLED (may be different controllers depending on screen size)
|
||||||
|
#define I2C_SDA 21
|
||||||
|
#define I2C_SCL 22
|
||||||
|
#define HAS_SCREEN 1 // Generates randomized BLE pin
|
||||||
|
|
||||||
|
// GNSS: Ai-Thinker GP-02 BDS/GNSS module
|
||||||
|
#define GPS_RX_PIN 16
|
||||||
|
#define GPS_TX_PIN 17
|
||||||
|
|
||||||
|
// Button
|
||||||
|
#define BUTTON_PIN 15 // Right side button - if not available, set device.button_gpio to 0 from Meshtastic client
|
||||||
|
|
||||||
|
// LEDs
|
||||||
|
#define LED_PIN 13 // Tx LED
|
||||||
|
#define USER_LED 2 // Rx LED
|
||||||
|
|
||||||
|
// Buzzer
|
||||||
|
#define PIN_BUZZER 33
|
||||||
|
|
||||||
|
// Battery sense
|
||||||
|
#define BATTERY_PIN 35
|
||||||
|
#define ADC_MULTIPLIER 2.01 // 100k + 100k, and add 1% tolerance
|
||||||
|
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
|
||||||
|
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
|
||||||
|
|
||||||
|
// SPI
|
||||||
|
#define LORA_SCK 18
|
||||||
|
#define LORA_MISO 19
|
||||||
|
#define LORA_MOSI 23
|
||||||
|
|
||||||
|
// LoRa
|
||||||
|
#define LORA_CS 5
|
||||||
|
#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module
|
||||||
|
#define LORA_RESET 27 // RST for SX1276, and for SX1262/SX1268
|
||||||
|
#define LORA_DIO1 12 // IRQ for SX1262/SX1268
|
||||||
|
#define LORA_DIO2 RADIOLIB_NC // BUSY for SX1262/SX1268
|
||||||
|
#define LORA_DIO3 // NC, but used as TCXO supply by E22 module
|
||||||
|
#define LORA_RXEN 32 // RF switch RX (and E22 LNA) control by ESP32 GPIO
|
||||||
|
#define LORA_TXEN 25 // RF switch TX (and E22 PA) control by ESP32 GPIO
|
||||||
|
|
||||||
|
// RX/TX for RFM95/SX127x
|
||||||
|
#define RF95_RXEN LORA_RXEN
|
||||||
|
#define RF95_TXEN LORA_TXEN
|
||||||
|
// #define RF95_TCXO <GPIO#>
|
||||||
|
|
||||||
|
// common pinouts for SX126X modules
|
||||||
|
#define SX126X_CS 5
|
||||||
|
#define SX126X_DIO1 LORA_DIO1
|
||||||
|
#define SX126X_BUSY LORA_DIO2
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_RXEN LORA_RXEN
|
||||||
|
#define SX126X_TXEN LORA_TXEN
|
||||||
|
|
||||||
|
// Support alternative modules if soldered in place of E22
|
||||||
|
#define USE_RF95 // RFM95/SX127x
|
||||||
|
#define USE_SX1262
|
||||||
|
#define USE_SX1268
|
||||||
|
#define USE_LLCC68
|
||||||
|
|
||||||
|
// E22 TCXO support
|
||||||
|
#ifdef EBYTE_E22
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
[env:heltec-wireless-bridge]
|
[env:heltec-wireless-bridge]
|
||||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
|
board_level = extra
|
||||||
board = heltec_wifi_lora_32
|
board = heltec_wifi_lora_32
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags}
|
${esp32_base.build_flags}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[env:trackerd]
|
[env:trackerd]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
|
board_level = extra
|
||||||
board = pico32
|
board = pico32
|
||||||
board_build.f_flash = 80000000L
|
board_build.f_flash = 80000000L
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = bpi_picow_esp32_s3
|
board = bpi_picow_esp32_s3
|
||||||
board_check = true
|
board_check = true
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = partition-table-8MB.csv
|
||||||
;OpenOCD flash method
|
;OpenOCD flash method
|
||||||
;upload_protocol = esp-builtin
|
;upload_protocol = esp-builtin
|
||||||
;Normal method
|
;Normal method
|
||||||
@@ -26,6 +26,7 @@ extends = env:picomputer-s3
|
|||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${env:picomputer-s3.build_flags}
|
${env:picomputer-s3.build_flags}
|
||||||
|
-D MESHTASTIC_EXCLUDE_WEBSERVER=1
|
||||||
-D INPUTDRIVER_MATRIX_TYPE=1
|
-D INPUTDRIVER_MATRIX_TYPE=1
|
||||||
-D USE_PIN_BUZZER=PIN_BUZZER
|
-D USE_PIN_BUZZER=PIN_BUZZER
|
||||||
-D USE_SX127x
|
-D USE_SX127x
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include "variant.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define USB_VID 0x303a
|
||||||
|
#define USB_PID 0x1001
|
||||||
|
|
||||||
|
// The default Wire will be mapped to PMU and RTC
|
||||||
|
static const uint8_t SDA = 9;
|
||||||
|
static const uint8_t SCL = 40;
|
||||||
|
|
||||||
|
// Default SPI will be mapped to Radio
|
||||||
|
static const uint8_t SS = 12;
|
||||||
|
static const uint8_t MOSI = 11;
|
||||||
|
static const uint8_t MISO = 10;
|
||||||
|
static const uint8_t SCK = 13;
|
||||||
|
|
||||||
|
#define SPI_MOSI (11)
|
||||||
|
#define SPI_SCK (13)
|
||||||
|
#define SPI_MISO (10)
|
||||||
|
#define SPI_CS (12)
|
||||||
|
|
||||||
|
// LEDs
|
||||||
|
#define LED_BUILTIN LED_GREEN
|
||||||
|
|
||||||
|
#endif /* Pins_Arduino_h */
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
; rak_wismeshtap2 rak3112
|
||||||
|
|
||||||
|
[rak_wismeshtap_s3]
|
||||||
|
extends = esp32s3_base
|
||||||
|
board = wiscore_rak3312
|
||||||
|
board_check = true
|
||||||
|
upload_protocol = esptool
|
||||||
|
board_build.partitions = default_8MB.csv
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${esp32_base.build_flags}
|
||||||
|
-D RAK3312
|
||||||
|
-D RAK_WISMESH_TAP_V2
|
||||||
|
-I variants/esp32s3/rak_wismesh_tap_v2
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32s3_base.lib_deps}
|
||||||
|
lovyan03/LovyanGFX@^1.2.0
|
||||||
|
|
||||||
|
[ft5x06]
|
||||||
|
extends = mesh_tab_base
|
||||||
|
build_flags =
|
||||||
|
-D LGFX_TOUCH=FT5x06
|
||||||
|
-D LGFX_TOUCH_I2C_FREQ=100000
|
||||||
|
-D LGFX_TOUCH_I2C_PORT=0
|
||||||
|
-D LGFX_TOUCH_I2C_ADDR=0x38
|
||||||
|
-D LGFX_TOUCH_I2C_SDA=9
|
||||||
|
-D LGFX_TOUCH_I2C_SCL=40
|
||||||
|
-D LGFX_TOUCH_RST=-1
|
||||||
|
-D LGFX_TOUCH_INT=39
|
||||||
|
|
||||||
|
[env:rak_wismesh_tap_v2-tft]
|
||||||
|
extends = rak_wismeshtap_s3
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${rak_wismeshtap_s3.build_flags}
|
||||||
|
-D CONFIG_ARDUHAL_ESP_LOG
|
||||||
|
-D CONFIG_ARDUHAL_LOG_COLORS=1
|
||||||
|
-D CONFIG_DISABLE_HAL_LOCKS=1
|
||||||
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
|
-D LV_CONF_INCLUDE_SIMPLE
|
||||||
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||||
|
-D LV_USE_SYSMON=0
|
||||||
|
-D LV_USE_PROFILER=0
|
||||||
|
-D LV_USE_PERF_MONITOR=0
|
||||||
|
-D LV_USE_MEM_MONITOR=0
|
||||||
|
-D LV_USE_LOG=0
|
||||||
|
-D LV_BUILD_TEST=0
|
||||||
|
-D USE_LOG_DEBUG
|
||||||
|
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
||||||
|
-D RADIOLIB_SPI_PARANOID=0
|
||||||
|
-D INPUTDRIVER_BUTTON_TYPE=0
|
||||||
|
-D HAS_SDCARD
|
||||||
|
-D HAS_SCREEN=0
|
||||||
|
-D HAS_TFT=1
|
||||||
|
-D USE_PIN_BUZZER=PIN_BUZZER
|
||||||
|
-D RAM_SIZE=5120
|
||||||
|
-D LGFX_DRIVER_TEMPLATE
|
||||||
|
-D LGFX_DRIVER=LGFX_GENERIC
|
||||||
|
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\"
|
||||||
|
-D LGFX_PIN_SCK=13
|
||||||
|
-D LGFX_PIN_MOSI=11
|
||||||
|
-D LGFX_PIN_MISO=10
|
||||||
|
-D LGFX_PIN_DC=42
|
||||||
|
-D LGFX_PIN_CS=12
|
||||||
|
-D LGFX_PIN_RST=-1
|
||||||
|
-D LGFX_PIN_BL=41
|
||||||
|
-D VIEW_320x240
|
||||||
|
-D USE_PACKET_API
|
||||||
|
${ft5x06.build_flags}
|
||||||
|
-D LGFX_SCREEN_WIDTH=240
|
||||||
|
-D LGFX_SCREEN_HEIGHT=320
|
||||||
|
-D DISPLAY_SIZE=320x240 ; landscape mode
|
||||||
|
-D LGFX_PANEL=ST7789
|
||||||
|
-D LGFX_ROTATION=1
|
||||||
|
-D LGFX_TOUCH_X_MIN=0
|
||||||
|
-D LGFX_TOUCH_X_MAX=239
|
||||||
|
-D LGFX_TOUCH_Y_MIN=0
|
||||||
|
-D LGFX_TOUCH_Y_MAX=319
|
||||||
|
-D LGFX_TOUCH_ROTATION=2
|
||||||
|
-D LGFX_CFG_HOST=SPI3_HOST
|
||||||
|
-D MAP_FULL_REDRAW=1
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${rak_wismeshtap_s3.lib_deps}
|
||||||
|
${device-ui_base.lib_deps}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#ifndef _VARIANT_RAK_WISMESHTAP_V2_H
|
||||||
|
#define _VARIANT_RAK_WISMESHTAP_V2_H
|
||||||
|
|
||||||
|
#define I2C_SDA 9
|
||||||
|
#define I2C_SCL 40
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
|
||||||
|
#define LORA_SCK 5
|
||||||
|
#define LORA_MISO 3
|
||||||
|
#define LORA_MOSI 6
|
||||||
|
#define LORA_CS 7
|
||||||
|
#define LORA_RESET 8
|
||||||
|
|
||||||
|
#ifdef USE_SX1262
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 47
|
||||||
|
#define SX126X_BUSY 48
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SX126X_POWER_EN (4)
|
||||||
|
|
||||||
|
#define PIN_POWER_EN PIN_3V3_EN
|
||||||
|
#define PIN_3V3_EN (14)
|
||||||
|
|
||||||
|
#define LED_GREEN 46
|
||||||
|
#define LED_BLUE 45
|
||||||
|
|
||||||
|
#define PIN_LED1 LED_GREEN
|
||||||
|
#define PIN_LED2 LED_BLUE
|
||||||
|
|
||||||
|
#define LED_CONN LED_BLUE
|
||||||
|
#define LED_PIN LED_GREEN
|
||||||
|
#define ledOff(pin) pinMode(pin, INPUT)
|
||||||
|
|
||||||
|
#define LED_STATE_ON 1 // State when LED is litted
|
||||||
|
|
||||||
|
#define HAS_GPS 1
|
||||||
|
#define GPS_TX_PIN 43
|
||||||
|
#define GPS_RX_PIN 44
|
||||||
|
|
||||||
|
#define SPI_MOSI (11)
|
||||||
|
#define SPI_SCK (13)
|
||||||
|
#define SPI_MISO (10)
|
||||||
|
#define SPI_CS (12)
|
||||||
|
|
||||||
|
#define HAS_BUTTON 1
|
||||||
|
#define BUTTON_PIN 0
|
||||||
|
|
||||||
|
#define CANNED_MESSAGE_MODULE_ENABLE 1
|
||||||
|
#define USE_VIRTUAL_KEYBOARD 1
|
||||||
|
|
||||||
|
#define BATTERY_PIN 1
|
||||||
|
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
|
||||||
|
#define ADC_MULTIPLIER 1.667
|
||||||
|
|
||||||
|
#define PIN_BUZZER 38
|
||||||
|
|
||||||
|
#define HAS_SDCARD 1
|
||||||
|
#define SDCARD_USE_SPI1 1
|
||||||
|
#define SDCARD_CS 2
|
||||||
|
|
||||||
|
#define SPI_FREQUENCY 40000000
|
||||||
|
#define SPI_READ_FREQUENCY 16000000
|
||||||
|
|
||||||
|
#define SD_SPI_FREQUENCY 50000000
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -6,7 +6,7 @@ platform_packages =
|
|||||||
|
|
||||||
board = seeed-sensecap-indicator
|
board = seeed-sensecap-indicator
|
||||||
board_check = true
|
board_check = true
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = partition-table-8MB.csv
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
|
|
||||||
build_flags = ${esp32_base.build_flags}
|
build_flags = ${esp32_base.build_flags}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
|||||||
lewisxhe/SensorLib@0.3.1
|
lewisxhe/SensorLib@0.3.1
|
||||||
https://github.com/pschatzmann/arduino-audio-driver/archive/refs/tags/v0.1.3.zip
|
https://github.com/pschatzmann/arduino-audio-driver/archive/refs/tags/v0.1.3.zip
|
||||||
https://github.com/mverch67/BQ27220/archive/07d92be846abd8a0258a50c23198dac0858b22ed.zip
|
https://github.com/mverch67/BQ27220/archive/07d92be846abd8a0258a50c23198dac0858b22ed.zip
|
||||||
https://github.com/mverch67/RotaryEncoder
|
https://github.com/mverch67/RotaryEncoder/archive/25a59d5745a6645536f921427d80b08e78f886d4.zip
|
||||||
|
|
||||||
[env:tlora-pager-tft]
|
[env:tlora-pager-tft]
|
||||||
board_level = extra
|
board_level = extra
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[env:unphone]
|
[env:unphone]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = unphone
|
board = unphone
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = partition-table-8MB.csv
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
@@ -20,6 +20,7 @@ build_flags =
|
|||||||
-D UNPHONE_LORA=0
|
-D UNPHONE_LORA=0
|
||||||
-D UNPHONE_FACTORY_MODE=0
|
-D UNPHONE_FACTORY_MODE=0
|
||||||
-D USE_SX127x
|
-D USE_SX127x
|
||||||
|
-D SDCARD_CS=43
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${esp32s3_base.build_src_filter}
|
${esp32s3_base.build_src_filter}
|
||||||
@@ -41,6 +42,7 @@ build_flags =
|
|||||||
-D HAS_SCREEN=1
|
-D HAS_SCREEN=1
|
||||||
-D HAS_TFT=1
|
-D HAS_TFT=1
|
||||||
-D HAS_SDCARD
|
-D HAS_SDCARD
|
||||||
|
-D SDCARD_CS=43
|
||||||
-D DISPLAY_SET_RESOLUTION
|
-D DISPLAY_SET_RESOLUTION
|
||||||
-D RAM_SIZE=6144
|
-D RAM_SIZE=6144
|
||||||
-D LV_CACHE_DEF_SIZE=2097152
|
-D LV_CACHE_DEF_SIZE=2097152
|
||||||
|
|||||||
@@ -52,7 +52,6 @@
|
|||||||
#undef GPS_TX_PIN
|
#undef GPS_TX_PIN
|
||||||
|
|
||||||
#define SD_SPI_FREQUENCY 25000000
|
#define SD_SPI_FREQUENCY 25000000
|
||||||
#define SDCARD_CS 43
|
|
||||||
|
|
||||||
#define LED_PIN 13 // the red part of the RGB LED
|
#define LED_PIN 13 // the red part of the RGB LED
|
||||||
#define LED_STATE_ON 0 // State when LED is lit
|
#define LED_STATE_ON 0 // State when LED is lit
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user