diff --git a/.env.example b/.env.example
new file mode 100644
index 000000000..72d95970a
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,4 @@
+# Absolute path to the local meshtastic config.yaml file
+CONFIG_PATH=/path/to/meshtastic/config.yaml
+# USB device to passthrough (`lsusb -t`: look for `ch341`)
+USB_DEVICE=/dev/bus/usb/001/037
diff --git a/.github/workflows/build_docker.yml b/.github/workflows/build_docker.yml
index bb5a394fd..13817a8cf 100644
--- a/.github/workflows/build_docker.yml
+++ b/.github/workflows/build_docker.yml
@@ -10,12 +10,6 @@ jobs:
build-native:
runs-on: ubuntu-latest
steps:
- - name: Install libs needed for native build
- shell: bash
- run: |
- sudo apt-get update --fix-missing
- sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev
-
- name: Checkout code
uses: actions/checkout@v4
with:
@@ -23,21 +17,6 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- - name: Upgrade python tools
- shell: bash
- run: |
- python -m pip install --upgrade pip
- pip install -U platformio adafruit-nrfutil
- pip install -U meshtastic --pre
-
- - name: Upgrade platformio
- shell: bash
- run: |
- pio upgrade
-
- - name: Build Native
- run: bin/build-native.sh
-
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
diff --git a/Dockerfile b/Dockerfile
index ca216e04b..f3b294a5b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,32 +1,29 @@
-FROM debian:bookworm-slim AS builder
+# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
+# trunk-ignore-all(hadolint/DL3008): Use latest version of apt packages for buildchain
+# trunk-ignore-all(trivy/DS002): We must run as root for this container
+# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
+# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
+FROM python:3.12-bookworm AS builder
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
-# http://bugs.python.org/issue19846
-# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
-ENV LANG C.UTF-8
-
-# Install build deps
-USER root
-
-# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
-# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
-RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \
- ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \
- libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config && \
- apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware
-
-RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh && chown mesh:mesh /tmp/firmware
-USER mesh
+# Install Dependencies
+ENV PIP_ROOT_USER_ACTION=ignore
+RUN apt-get update && apt-get install --no-install-recommends -y wget g++ zip git ca-certificates \
+ libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev \
+ libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config && \
+ apt-get clean && rm -rf /var/lib/apt/lists/* && \
+ pip install --no-cache-dir -U platformio==6.1.16 && \
+ mkdir /tmp/firmware
+# Copy source code
WORKDIR /tmp/firmware
-RUN python3 -m venv /tmp/firmware
-RUN bash -o pipefail -c "source bin/activate; pip3 install --no-cache-dir -U platformio==6.1.15"
-# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm
-COPY --chown=mesh:mesh . /tmp/firmware
-RUN bash -o pipefail -c "source ./bin/activate && bash ./bin/build-native.sh"
-RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
+COPY . /tmp/firmware
+
+# Build
+RUN bash ./bin/build-native.sh && \
+ cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
##### PRODUCTION BUILD #############
@@ -35,20 +32,25 @@ FROM debian:bookworm-slim
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
-# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
-# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
-RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libulfius2.7 libusb-1.0-0-dev liborcania2.3 libssl3 && \
- apt-get clean && rm -rf /var/lib/apt/lists/*
+# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
+USER root
-RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
-USER mesh
+RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libulfius2.7 libusb-1.0-0-dev liborcania2.3 libssl3 && \
+ apt-get clean && rm -rf /var/lib/apt/lists/* \
+ && mkdir -p /var/lib/meshtasticd \
+ && mkdir -p /etc/meshtasticd/config.d
-WORKDIR /home/mesh
-COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
+# Fetch compiled binary from the builder
+COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
+# Copy config templates
+COPY ./bin/config.d /etc/meshtasticd/available.d
-RUN mkdir data
-VOLUME /home/mesh/data
+WORKDIR /var/lib/meshtasticd
+VOLUME /var/lib/meshtasticd
-CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
+# Expose Meshtastic TCP API port from the host
+EXPOSE 4403
+
+CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ]
HEALTHCHECK NONE
\ No newline at end of file
diff --git a/alpine.Dockerfile b/alpine.Dockerfile
new file mode 100644
index 000000000..115602b3b
--- /dev/null
+++ b/alpine.Dockerfile
@@ -0,0 +1,42 @@
+# trunk-ignore-all(trivy/DS002): We must run as root for this container
+# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
+# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
+
+FROM python:3.12-alpine3.21 AS builder
+
+ENV PIP_ROOT_USER_ACTION=ignore
+RUN apk add bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \
+ libusb-dev i2c-tools-dev openssl-dev pkgconf argp-standalone && \
+ pip install --no-cache-dir -U platformio==6.1.16 && \
+ mkdir /tmp/firmware
+
+WORKDIR /tmp/firmware
+COPY . /tmp/firmware
+
+# Create small package (no debugging symbols)
+# Add `argp` for musl
+ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp"
+
+RUN bash ./bin/build-native.sh && \
+ cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
+
+# ##### PRODUCTION BUILD #############
+
+FROM alpine:3.21
+
+# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
+USER root
+
+RUN apk add libstdc++ libgpiod yaml-cpp libusb i2c-tools \
+ && mkdir -p /var/lib/meshtasticd \
+ && mkdir -p /etc/meshtasticd/config.d
+COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
+
+WORKDIR /var/lib/meshtasticd
+VOLUME /var/lib/meshtasticd
+
+EXPOSE 4403
+
+CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ]
+
+HEALTHCHECK NONE
\ No newline at end of file
diff --git a/boards/mesh-tab.json b/boards/mesh-tab.json
new file mode 100644
index 000000000..52c65bf77
--- /dev/null
+++ b/boards/mesh-tab.json
@@ -0,0 +1,42 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "esp32s3_out.ld",
+ "partitions": "default_16MB.csv",
+ "memory_type": "qio_qspi"
+ },
+ "core": "esp32",
+ "extra_flags": [
+ "-DBOARD_HAS_PSRAM",
+ "-DARDUINO_USB_CDC_ON_BOOT=1",
+ "-DARDUINO_USB_MODE=0",
+ "-DARDUINO_RUNNING_CORE=1",
+ "-DARDUINO_EVENT_RUNNING_CORE=1"
+ ],
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "qio",
+ "hwids": [["0x303A", "0x80D6"]],
+ "mcu": "esp32s3",
+ "variant": "mesh-tab"
+ },
+ "connectivity": ["wifi", "bluetooth", "lora"],
+ "debug": {
+ "default_tool": "esp-builtin",
+ "onboard_tools": ["esp-builtin"],
+ "openocd_target": "esp32s3.cfg"
+ },
+ "frameworks": ["arduino", "espidf"],
+ "name": "ESP32-S3 WROOM-1 N16R2 (16 MB FLASH, 2 MB PSRAM)",
+ "upload": {
+ "flash_size": "16MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 16777216,
+ "use_1200bps_touch": true,
+ "wait_for_upload_port": true,
+ "require_upload_port": true,
+ "speed": 460800
+ },
+ "url": "https://github.com/valzzu/Mesh-Tab",
+ "vendor": "Espressif"
+}
diff --git a/boards/seeed-sensecap-indicator.json b/boards/seeed-sensecap-indicator.json
index 3fc57126f..0a02fc882 100644
--- a/boards/seeed-sensecap-indicator.json
+++ b/boards/seeed-sensecap-indicator.json
@@ -15,10 +15,12 @@
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
+ "f_boot": "120000000L",
+ "boot": "qio",
"flash_mode": "qio",
"hwids": [["0x1A86", "0x7523"]],
"mcu": "esp32s3",
- "variant": "esp32s3r8"
+ "variant": "esp32s3"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
@@ -32,9 +34,9 @@
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
- "require_upload_port": true,
+ "require_upload_port": false,
"use_1200bps_touch": true,
- "wait_for_upload_port": true,
+ "wait_for_upload_port": false,
"speed": 921600
},
"url": "https://www.seeedstudio.com/Indicator-for-Meshtastic.html",
diff --git a/boards/t-deck.json b/boards/t-deck.json
index d62ec48e6..b112921b9 100644
--- a/boards/t-deck.json
+++ b/boards/t-deck.json
@@ -10,7 +10,7 @@
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
- "-DARDUINO_EVENT_RUNNING_CORE=0"
+ "-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
diff --git a/docker-compose.yml b/docker-compose.yml
index 82f2647e8..4aac318c5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,13 +1,26 @@
-version: "3.7"
+# USB-Based Meshtastic container-node!
+
+# Copy .env.example to .env and set the USB_DEVICE and CONFIG_PATH variables
services:
meshtastic-node:
build: .
- deploy:
- mode: replicated
- replicas: 4
- networks:
- - mesh
+ container_name: meshtasticd
-networks:
- mesh:
+ # Pass USB device through to the container
+ devices:
+ - "${USB_DEVICE}"
+
+ # Mount local config file and named volume for data persistence
+ volumes:
+ - "${CONFIG_PATH}:/etc/meshtasticd/config.yaml:ro"
+ - meshtastic_data:/var/lib/meshtasticd
+
+ # Forward the container’s port 4403 to the host
+ ports:
+ - 4403:4403
+
+ restart: unless-stopped
+
+volumes:
+ meshtastic_data:
diff --git a/platformio.ini b/platformio.ini
index 41f1ca764..bf50b7646 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -81,7 +81,8 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_LORAWAN=1
-DMESHTASTIC_EXCLUDE_DROPZONE=1
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
- -DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
+ -DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
+ -DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
#-DBUILD_EPOCH=$UNIX_TIME
;-D OLED_PL
@@ -153,7 +154,6 @@ lib_deps =
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.2.13
ClosedCube OPT3001@1.1.2
emotibit/EmotiBit MLX90632@1.0.8
- sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
adafruit/Adafruit MLX90614 Library@2.1.5
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
boschsensortec/BME68x Sensor Library@1.1.40407
@@ -161,4 +161,7 @@ lib_deps =
mprograms/QMC5883LCompass@1.2.3
dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
- robtillaart/INA226@0.6.0
+ robtillaart/INA226@0.6.0
+
+ ; Health Sensor Libraries
+ sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
\ No newline at end of file
diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp
index 6cd17dac8..df46c1941 100644
--- a/src/FSCommon.cpp
+++ b/src/FSCommon.cpp
@@ -55,6 +55,15 @@ extern "C" void lfs_assert(const char *reason)
{
LOG_ERROR("LFS assert: %s", reason);
lfs_assert_failed = true;
+
+#ifndef ARCH_PORTDUINO
+#ifdef FSCom
+ // CORRUPTED FILESYSTEM. This causes bootloop so
+ // might as well try formatting now.
+ LOG_ERROR("Trying FSCom.format()");
+ FSCom.format();
+#endif
+#endif
}
/**
diff --git a/src/configuration.h b/src/configuration.h
index b5727508d..994f1e72e 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -250,6 +250,9 @@ along with this program. If not, see .
#ifndef HAS_SCREEN
#define HAS_SCREEN 0
#endif
+#ifndef HAS_TFT
+#define HAS_TFT 0
+#endif
#ifndef HAS_WIRE
#define HAS_WIRE 0
#endif
@@ -312,6 +315,7 @@ along with this program. If not, see .
#define MESHTASTIC_EXCLUDE_AUDIO 1
#define MESHTASTIC_EXCLUDE_DETECTIONSENSOR 1
#define MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR 1
+#define MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY 1
#define MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION 1
#define MESHTASTIC_EXCLUDE_PAXCOUNTER 1
#define MESHTASTIC_EXCLUDE_POWER_TELEMETRY 1
@@ -361,4 +365,4 @@ along with this program. If not, see .
#endif
#include "DebugConfiguration.h"
-#include "RF95Configuration.h"
\ No newline at end of file
+#include "RF95Configuration.h"
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 6e695c22f..a786f874d 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -458,11 +458,11 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
i2cBus->endTransmission();
len = i2cBus->readBytes(info, 5);
if (len == 5 && memcmp(expectedInfo, info, len) == 0) {
- LOG_INFO("NXP SE050 crypto chip found\n");
+ LOG_INFO("NXP SE050 crypto chip found");
type = NXP_SE050;
} else {
- LOG_INFO("FT6336U touchscreen found\n");
+ LOG_INFO("FT6336U touchscreen found");
type = FT6336U;
}
break;
@@ -510,4 +510,4 @@ void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
{
LOG_INFO("%s found at address 0x%x", device, address);
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index 27ea6f414..4cfb8701e 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -1718,7 +1718,7 @@ void Screen::setup()
#endif
serialSinceMsec = millis();
-#if ARCH_PORTDUINO
+#if ARCH_PORTDUINO && !HAS_TFT
if (settingsMap[touchscreenModule]) {
touchScreenImpl1 =
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast(dispdev)->getTouch);
diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp
index 87c3f7de9..4f2af670b 100644
--- a/src/graphics/TFTDisplay.cpp
+++ b/src/graphics/TFTDisplay.cpp
@@ -347,7 +347,7 @@ static LGFX *tft = nullptr;
#include // Graphics and font library for ILI9342 driver chip
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
-#elif ARCH_PORTDUINO && HAS_SCREEN != 0
+#elif ARCH_PORTDUINO && HAS_SCREEN != 0 && !HAS_TFT
#include // Graphics and font library for ST7735 driver chip
class LGFX : public lgfx::LGFX_Device
diff --git a/src/input/MPR121Keyboard.cpp b/src/input/MPR121Keyboard.cpp
index 078d80272..9bca6801d 100644
--- a/src/input/MPR121Keyboard.cpp
+++ b/src/input/MPR121Keyboard.cpp
@@ -29,6 +29,8 @@
#define _MPR121_REG_CONFIG1 0x5C
#define _MPR121_REG_CONFIG2 0x5D
#define _MPR121_REG_ELECTRODE_CONFIG 0x5E
+#define _MPR121_REG_AUTOCONF_CTRL0 0x7B
+#define _MPR121_REG_AUTOCONF_CTRL1 0x7C
#define _MPR121_REG_SOFT_RESET 0x80
#define _KEY_MASK 0x0FFF // Key mask for the first 12 bits
@@ -87,7 +89,7 @@ uint8_t MPR121_KeyMap[12] = {2, 5, 8, 11, 1, 4, 7, 10, 0, 3, 6, 9};
MPR121Keyboard::MPR121Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
{
- // LOG_DEBUG("MPR121 @ %02x\n", m_addr);
+ // LOG_DEBUG("MPR121 @ %02x", m_addr);
state = Init;
last_key = -1;
last_tap = 0L;
@@ -132,18 +134,18 @@ void MPR121Keyboard::reset()
writeRegister(_MPR121_REG_ELECTRODE_CONFIG, 0x00);
delay(100);
- LOG_DEBUG("MPR121 Configure");
+ LOG_DEBUG("MPR121 Configuring");
// Set touch release thresholds
for (uint8_t i = 0; i < 12; i++) {
// Set touch threshold
- writeRegister(_MPR121_REG_TOUCH_THRESHOLD + (i * 2), 15);
+ writeRegister(_MPR121_REG_TOUCH_THRESHOLD + (i * 2), 10);
delay(20);
// Set release threshold
- writeRegister(_MPR121_REG_RELEASE_THRESHOLD + (i * 2), 7);
+ writeRegister(_MPR121_REG_RELEASE_THRESHOLD + (i * 2), 5);
delay(20);
}
// Configure filtering and baseline registers
- writeRegister(_MPR121_REG_MAX_HALF_DELTA_RISING, 0x01);
+ writeRegister(_MPR121_REG_MAX_HALF_DELTA_RISING, 0x05);
delay(20);
writeRegister(_MPR121_REG_MAX_HALF_DELTA_FALLING, 0x01);
delay(20);
@@ -153,7 +155,7 @@ void MPR121Keyboard::reset()
delay(20);
writeRegister(_MPR121_REG_NOISE_HALF_DELTA_TOUCHED, 0x00);
delay(20);
- writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_RISING, 0x0e);
+ writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_RISING, 0x05);
delay(20);
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_FALLING, 0x01);
delay(20);
@@ -165,18 +167,19 @@ void MPR121Keyboard::reset()
delay(20);
writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_TOUCHED, 0x00);
delay(20);
- // Set Debounce to 0x02
- writeRegister(_MPR121_REG_DEBOUNCE, 0x00);
+ writeRegister(_MPR121_REG_AUTOCONF_CTRL0, 0x04); // Auto-config enable
delay(20);
- // Set Filter1 itterations and discharge current 6x and 16uA respectively (0x10)
- writeRegister(_MPR121_REG_CONFIG1, 0x10);
+ writeRegister(_MPR121_REG_AUTOCONF_CTRL1, 0x00); // Ensure no auto-config interrupt
delay(20);
- // Set CDT to 0.5us, Filter2 itterations to 4x, and Sample interval = 0 (0x20)
- writeRegister(_MPR121_REG_CONFIG2, 0x20);
+ writeRegister(_MPR121_REG_DEBOUNCE, 0x02);
+ delay(20);
+ writeRegister(_MPR121_REG_CONFIG1, 0x20);
+ delay(20);
+ writeRegister(_MPR121_REG_CONFIG2, 0x21);
delay(20);
// Enter run mode by Seting partial filter calibration tracking, disable proximity detection, enable 12 channels
writeRegister(_MPR121_REG_ELECTRODE_CONFIG,
- ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH);
+ ECR_CALIBRATION_TRACK_FROM_FULL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH);
delay(100);
LOG_DEBUG("MPR121 Run");
state = Idle;
@@ -427,4 +430,4 @@ void MPR121Keyboard::writeRegister(uint8_t reg, uint8_t value)
if (writeCallback) {
writeCallback(m_addr, data[0], &(data[1]), 1);
}
-}
+}
\ No newline at end of file
diff --git a/src/input/TouchScreenBase.cpp b/src/input/TouchScreenBase.cpp
index a63203362..d2f7b54f8 100644
--- a/src/input/TouchScreenBase.cpp
+++ b/src/input/TouchScreenBase.cpp
@@ -113,13 +113,13 @@ int32_t TouchScreenBase::runOnce()
if (_tapped) {
_tapped = false;
e.touchEvent = static_cast(TOUCH_ACTION_TAP);
- LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
+ LOG_DEBUG("action TAP(%d/%d)", _last_x, _last_y);
}
} else {
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
_tapped = false;
e.touchEvent = static_cast(TOUCH_ACTION_TAP);
- LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
+ LOG_DEBUG("action TAP(%d/%d)", _last_x, _last_y);
}
}
#else
@@ -156,4 +156,4 @@ void TouchScreenBase::hapticFeedback()
drv.setWaveform(1, 0); // end waveform
drv.go();
#endif
-}
\ No newline at end of file
+}
diff --git a/src/main.cpp b/src/main.cpp
index f4bb11535..5982e709d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -40,6 +40,7 @@
#include
#ifdef ARCH_ESP32
+#include "freertosinc.h"
#if !MESHTASTIC_EXCLUDE_WEBSERVER
#include "mesh/http/WebServer.h"
#endif
@@ -173,6 +174,8 @@ std::pair nodeTelemetrySensorsMap[_meshtastic_TelemetrySenso
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
+const char *firmware_version = optstr(APP_VERSION_SHORT);
+
const char *getDeviceName()
{
uint8_t dmac[6];
@@ -1275,4 +1278,4 @@ void loop()
mainDelay.delay(delayMsec);
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp
index e29c596df..f94540905 100644
--- a/src/mesh/FloodingRouter.cpp
+++ b/src/mesh/FloodingRouter.cpp
@@ -24,11 +24,15 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
printPacket("Ignore dupe incoming msg", p);
rxDupe++;
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
- config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
+ config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
+ config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) {
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;
}
+ if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) {
+ iface->clampToLateRebroadcastWindow(getFrom(p), p->id);
+ }
/* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when
the ACK got lost, we will handle the packet again to make sure it gets an ACK to its packet. */
diff --git a/src/mesh/MeshPacketQueue.cpp b/src/mesh/MeshPacketQueue.cpp
index 99ef41c1e..d7ee65800 100644
--- a/src/mesh/MeshPacketQueue.cpp
+++ b/src/mesh/MeshPacketQueue.cpp
@@ -16,6 +16,12 @@ inline uint32_t getPriority(const meshtastic_MeshPacket *p)
bool CompareMeshPacketFunc(const meshtastic_MeshPacket *p1, const meshtastic_MeshPacket *p2)
{
assert(p1 && p2);
+
+ // If one packet is in the late transmit window, prefer the other one
+ if ((bool)p1->tx_after != (bool)p2->tx_after) {
+ return !p1->tx_after;
+ }
+
auto p1p = getPriority(p1), p2p = getPriority(p2);
// If priorities differ, use that
// for equal priorities, prefer packets already on mesh.
@@ -94,11 +100,11 @@ meshtastic_MeshPacket *MeshPacketQueue::getFront()
}
/** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */
-meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
+meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool tx_normal, bool tx_late)
{
for (auto it = queue.begin(); it != queue.end(); it++) {
auto p = (*it);
- if (getFrom(p) == from && p->id == id) {
+ if (getFrom(p) == from && p->id == id && ((tx_normal && !p->tx_after) || (tx_late && p->tx_after))) {
queue.erase(it);
return p;
}
@@ -114,9 +120,10 @@ bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
if (queue.empty()) {
return false; // No packets to replace
}
+
// Check if the packet at the back has a lower priority than the new packet
auto &backPacket = queue.back();
- if (backPacket->priority < p->priority) {
+ if (!backPacket->tx_after && backPacket->priority < p->priority) {
// Remove the back packet
packetPool.release(backPacket);
queue.pop_back();
@@ -125,6 +132,19 @@ bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
return true;
}
+ if (backPacket->tx_after) {
+ // Check if there's a non-late packet with lower priority
+ auto it = queue.end();
+ auto refPacket = *--it;
+ for (; refPacket->tx_after && it != queue.begin(); refPacket = *--it)
+ ;
+ if (!refPacket->tx_after && refPacket->priority < p->priority) {
+ packetPool.release(refPacket);
+ enqueue(refPacket);
+ return true;
+ }
+ }
+
// If the back packet's priority is not lower, no replacement occurs
return false;
}
\ No newline at end of file
diff --git a/src/mesh/MeshPacketQueue.h b/src/mesh/MeshPacketQueue.h
index 3c28fc5ce..b41a214b9 100644
--- a/src/mesh/MeshPacketQueue.h
+++ b/src/mesh/MeshPacketQueue.h
@@ -36,5 +36,5 @@ class MeshPacketQueue
meshtastic_MeshPacket *getFront();
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
- meshtastic_MeshPacket *remove(NodeNum from, PacketId id);
-};
+ meshtastic_MeshPacket *remove(NodeNum from, PacketId id, bool tx_normal = true, bool tx_late = true);
+};
\ No newline at end of file
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 2af85e4f5..9dbe92b7c 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -57,6 +57,7 @@ NodeDB *nodeDB = nullptr;
EXT_RAM_BSS_ATTR meshtastic_DeviceState devicestate;
meshtastic_MyNodeInfo &myNodeInfo = devicestate.my_node;
meshtastic_LocalConfig config;
+meshtastic_DeviceUIConfig uiconfig{.screen_brightness = 153, .screen_timeout = 30};
meshtastic_LocalModuleConfig moduleConfig;
meshtastic_ChannelFile channelFile;
@@ -895,6 +896,7 @@ void NodeDB::pickNewNodeNum()
static const char *prefFileName = "/prefs/db.proto";
static const char *configFileName = "/prefs/config.proto";
+static const char *uiconfigFileName = "/prefs/uiconfig.proto";
static const char *moduleConfigFileName = "/prefs/module.proto";
static const char *channelFileName = "/prefs/channels.proto";
@@ -1054,6 +1056,12 @@ void NodeDB::loadFromDisk()
}
}
+ state = loadProto(uiconfigFileName, meshtastic_DeviceUIConfig_size, sizeof(meshtastic_DeviceUIConfig),
+ &meshtastic_DeviceUIConfig_msg, &uiconfig);
+ if (state == LoadFileResult::LOAD_SUCCESS) {
+ LOG_INFO("Loaded UIConfig");
+ }
+
// 2.4.X - configuration migration to update new default intervals
if (moduleConfig.version < 23) {
LOG_DEBUG("ModuleConfig version %d is stale, upgrading to new default intervals", moduleConfig.version);
diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h
index 7e51a1240..c8c0d3170 100644
--- a/src/mesh/NodeDB.h
+++ b/src/mesh/NodeDB.h
@@ -29,6 +29,7 @@ extern meshtastic_DeviceState devicestate;
extern meshtastic_ChannelFile channelFile;
extern meshtastic_MyNodeInfo &myNodeInfo;
extern meshtastic_LocalConfig config;
+extern meshtastic_DeviceUIConfig uiconfig;
extern meshtastic_LocalModuleConfig moduleConfig;
extern meshtastic_User &owner;
extern meshtastic_Position localPosition;
diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp
index f49718c5e..8c1ba74c7 100644
--- a/src/mesh/PhoneAPI.cpp
+++ b/src/mesh/PhoneAPI.cpp
@@ -164,6 +164,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
*
* Our sending states progress in the following sequence (the client apps ASSUME THIS SEQUENCE, DO NOT CHANGE IT):
STATE_SEND_MY_INFO, // send our my info record
+ STATE_SEND_UIDATA,
STATE_SEND_OWN_NODEINFO,
STATE_SEND_METADATA,
STATE_SEND_CHANNELS
@@ -188,7 +189,6 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_NOTHING:
LOG_DEBUG("FromRadio=STATE_SEND_NOTHING");
break;
-
case STATE_SEND_MY_INFO:
LOG_DEBUG("FromRadio=STATE_SEND_MY_INFO");
// If the user has specified they don't want our node to share its location, make sure to tell the phone
@@ -196,11 +196,18 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag;
strncpy(myNodeInfo.pio_env, optstr(APP_ENV), sizeof(myNodeInfo.pio_env));
fromRadioScratch.my_info = myNodeInfo;
- state = STATE_SEND_OWN_NODEINFO;
+ state = STATE_SEND_UIDATA;
service->refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon.
break;
+ case STATE_SEND_UIDATA:
+ LOG_INFO("getFromRadio=STATE_SEND_UIDATA");
+ fromRadioScratch.which_payload_variant = meshtastic_FromRadio_deviceuiConfig_tag;
+ fromRadioScratch.deviceuiConfig = uiconfig;
+ state = STATE_SEND_OWN_NODEINFO;
+ break;
+
case STATE_SEND_OWN_NODEINFO: {
LOG_DEBUG("Send My NodeInfo");
auto us = nodeDB->readNextMeshNode(readIndex);
@@ -284,6 +291,9 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
LOG_DEBUG("Send config: sessionkey");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_sessionkey_tag;
break;
+ case meshtastic_Config_device_ui_tag: // NOOP!
+ fromRadioScratch.config.which_payload_variant = meshtastic_Config_device_ui_tag;
+ break;
default:
LOG_ERROR("Unknown config type %d", config_state);
}
@@ -518,6 +528,7 @@ bool PhoneAPI::available()
case STATE_SEND_NOTHING:
return false;
case STATE_SEND_MY_INFO:
+ case STATE_SEND_UIDATA:
case STATE_SEND_CHANNELS:
case STATE_SEND_CONFIG:
case STATE_SEND_MODULECONFIG:
@@ -657,4 +668,4 @@ int PhoneAPI::onNotify(uint32_t newValue)
}
return timeout ? -1 : 0; // If we timed out, MeshService should stop iterating through observers as we just removed one
-}
\ No newline at end of file
+}
diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h
index 3247fee5c..681b244c8 100644
--- a/src/mesh/PhoneAPI.h
+++ b/src/mesh/PhoneAPI.h
@@ -34,6 +34,7 @@ class PhoneAPI
{
enum State {
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
+ STATE_SEND_UIDATA, // send stored data for device-ui
STATE_SEND_MY_INFO, // send our my info record
STATE_SEND_OWN_NODEINFO,
STATE_SEND_METADATA,
@@ -148,6 +149,9 @@ class PhoneAPI
*/
virtual void onNowHasData(uint32_t fromRadioNum) {}
+ /// begin a new connection
+ void handleStartConfig();
+
private:
void releasePhonePacket();
@@ -157,9 +161,6 @@ class PhoneAPI
void releaseClientNotification();
- /// begin a new connection
- void handleStartConfig();
-
bool wasSeenRecently(uint32_t packetId);
/**
@@ -170,4 +171,4 @@ class PhoneAPI
/// If the mesh service tells us fromNum has changed, tell the phone
virtual int onNotify(uint32_t newValue) override;
-};
\ No newline at end of file
+};
diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp
index 5161ac41f..b1403f3b6 100644
--- a/src/mesh/RadioInterface.cpp
+++ b/src/mesh/RadioInterface.cpp
@@ -254,8 +254,8 @@ uint32_t RadioInterface::getTxDelayMsec()
return random(0, pow(2, CWsize)) * slotTimeMsec;
}
-/** The delay to use when we want to flood a message */
-uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
+/** The CW size to use when calculating SNR_based delays */
+uint8_t RadioInterface::getCWsize(float snr)
{
// The minimum value for a LoRa SNR
const uint32_t SNR_MIN = -20;
@@ -263,10 +263,24 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
// The maximum value for a LoRa SNR
const uint32_t SNR_MAX = 15;
+ return map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax);
+}
+
+/** The worst-case SNR_based packet delay */
+uint32_t RadioInterface::getTxDelayMsecWeightedWorst(float snr)
+{
+ uint8_t CWsize = getCWsize(snr);
+ // offset the maximum delay for routers: (2 * CWmax * slotTimeMsec)
+ return (2 * CWmax * slotTimeMsec) + pow(2, CWsize) * slotTimeMsec;
+}
+
+/** The delay to use when we want to flood a message */
+uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
+{
// high SNR = large CW size (Long Delay)
// low SNR = small CW size (Short Delay)
uint32_t delay = 0;
- uint8_t CWsize = map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax);
+ uint8_t CWsize = getCWsize(snr);
// LOG_DEBUG("rx_snr of %f so setting CWsize to:%d", snr, CWsize);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
@@ -313,6 +327,7 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
out += DEBUG_PORT.mt_sprintf(" failId=%08x", s.ackVariant.fail_id); */
} else {
out += " encrypted";
+ out += DEBUG_PORT.mt_sprintf(" len=%d", p->encrypted.size + sizeof(PacketHeader));
}
if (p->rx_time != 0)
@@ -622,4 +637,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
sendingPacket = p;
return p->encrypted.size + sizeof(PacketHeader);
-}
\ No newline at end of file
+}
diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h
index 89a4c7087..652b2269c 100644
--- a/src/mesh/RadioInterface.h
+++ b/src/mesh/RadioInterface.h
@@ -173,9 +173,18 @@ class RadioInterface
/** The delay to use when we want to send something */
uint32_t getTxDelayMsec();
+ /** The CW to use when calculating SNR_based delays */
+ uint8_t getCWsize(float snr);
+
+ /** The worst-case SNR_based packet delay */
+ uint32_t getTxDelayMsecWeightedWorst(float snr);
+
/** The delay to use when we want to flood a message. Use a weighted scale based on SNR */
uint32_t getTxDelayMsecWeighted(float snr);
+ /** If the packet is not already in the late rebroadcast window, move it there */
+ virtual void clampToLateRebroadcastWindow(NodeNum from, PacketId id) { return; }
+
/**
* Calculate airtime per
* https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf
diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp
index e416160eb..997b1d6fe 100644
--- a/src/mesh/RadioLibInterface.cpp
+++ b/src/mesh/RadioLibInterface.cpp
@@ -235,12 +235,12 @@ void RadioLibInterface::onNotify(uint32_t notification)
case ISR_TX:
handleTransmitInterrupt();
startReceive();
- startTransmitTimer();
+ setTransmitDelay();
break;
case ISR_RX:
handleReceiveInterrupt();
startReceive();
- startTransmitTimer();
+ setTransmitDelay();
break;
case TRANSMIT_DELAY_COMPLETED:
@@ -250,23 +250,32 @@ void RadioLibInterface::onNotify(uint32_t notification)
if (!canSendImmediately()) {
setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
} else {
- if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
- startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
- setTransmitDelay();
+ meshtastic_MeshPacket *txp = txQueue.getFront();
+ assert(txp);
+ long delay_remaining = txp->tx_after ? txp->tx_after - millis() : 0;
+ if (delay_remaining > 0) {
+ // There's still some delay pending on this packet, so resume waiting for it to elapse
+ notifyLater(delay_remaining, TRANSMIT_DELAY_COMPLETED, false);
} else {
- // Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
- // actual transmission as short as possible
- meshtastic_MeshPacket *txp = txQueue.dequeue();
- assert(txp);
- bool sent = startSend(txp);
- if (sent) {
- // Packet has been sent, count it toward our TX airtime utilization.
- uint32_t xmitMsec = getPacketTime(txp);
- airTime->logAirtime(TX_LOG, xmitMsec);
+ if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
+ startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
+ setTransmitDelay();
+ } else {
+ // Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
+ // actual transmission as short as possible
+ txp = txQueue.dequeue();
+ assert(txp);
+ bool sent = startSend(txp);
+ if (sent) {
+ // Packet has been sent, count it toward our TX airtime utilization.
+ uint32_t xmitMsec = getPacketTime(txp);
+ airTime->logAirtime(TX_LOG, xmitMsec);
+ }
}
}
}
} else {
+ // Do nothing, because the queue is empty
}
break;
default:
@@ -277,15 +286,24 @@ void RadioLibInterface::onNotify(uint32_t notification)
void RadioLibInterface::setTransmitDelay()
{
meshtastic_MeshPacket *p = txQueue.getFront();
+ if (!p) {
+ return; // noop if there's nothing in the queue
+ }
+
// We want all sending/receiving to be done by our daemon thread.
// We use a delay here because this packet might have been sent in response to a packet we just received.
// So we want to make sure the other side has had a chance to reconfigure its radio.
- /* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
- * This assumption is valid because of the offset generated by the radio to account for the noise
- * floor.
- */
- if (p->rx_snr == 0 && p->rx_rssi == 0) {
+ if (p->tx_after) {
+ unsigned long add_delay = p->rx_rssi ? getTxDelayMsecWeighted(p->rx_snr) : getTxDelayMsec();
+ unsigned long now = millis();
+ p->tx_after = max(p->tx_after + add_delay, now + add_delay);
+ notifyLater(now - p->tx_after, TRANSMIT_DELAY_COMPLETED, false);
+ } else if (p->rx_snr == 0 && p->rx_rssi == 0) {
+ /* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
+ * This assumption is valid because of the offset generated by the radio to account for the noise
+ * floor.
+ */
startTransmitTimer(true);
} else {
// If there is a SNR, start a timer scaled based on that SNR.
@@ -312,6 +330,20 @@ void RadioLibInterface::startTransmitTimerSNR(float snr)
}
}
+/**
+ * If the packet is not already in the late rebroadcast window, move it there
+ */
+void RadioLibInterface::clampToLateRebroadcastWindow(NodeNum from, PacketId id)
+{
+ // Look for non-late packets only, so we don't do this twice!
+ meshtastic_MeshPacket *p = txQueue.remove(from, id, true, false);
+ if (p) {
+ p->tx_after = millis() + getTxDelayMsecWeightedWorst(p->rx_snr);
+ txQueue.enqueue(p);
+ LOG_DEBUG("Move existing queued packet to the late rebroadcast window %dms from now", p->tx_after - millis());
+ }
+}
+
void RadioLibInterface::handleTransmitInterrupt()
{
// This can be null if we forced the device to enter standby mode. In that case
diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h
index d6101ae37..dff58c9ad 100644
--- a/src/mesh/RadioLibInterface.h
+++ b/src/mesh/RadioLibInterface.h
@@ -140,10 +140,16 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
* doing the transmit */
void setTransmitDelay();
- /** random timer with certain min. and max. settings */
+ /**
+ * random timer with certain min. and max. settings
+ * @return Timestamp after which the packet may be sent
+ */
void startTransmitTimer(bool withDelay = true);
- /** timer scaled to SNR of to be flooded packet */
+ /**
+ * timer scaled to SNR of to be flooded packet
+ * @return Timestamp after which the packet may be sent
+ */
void startTransmitTimerSNR(float snr);
void handleTransmitInterrupt();
@@ -193,4 +199,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
virtual void setStandby();
const char *radioLibErr = "RadioLib err=";
+
+ /**
+ * If the packet is not already in the late rebroadcast window, move it there
+ */
+ void clampToLateRebroadcastWindow(NodeNum from, PacketId id);
};
\ No newline at end of file
diff --git a/src/mesh/aes-ccm.cpp b/src/mesh/aes-ccm.cpp
index 8bc2989bf..a650ba2fc 100644
--- a/src/mesh/aes-ccm.cpp
+++ b/src/mesh/aes-ccm.cpp
@@ -18,12 +18,9 @@ static void WPA_PUT_BE16(uint8_t *a, uint16_t val)
static void xor_aes_block(uint8_t *dst, const uint8_t *src)
{
- uint32_t *d = (uint32_t *)dst;
- uint32_t *s = (uint32_t *)src;
- *d++ ^= *s++;
- *d++ ^= *s++;
- *d++ ^= *s++;
- *d++ ^= *s++;
+ for (uint8_t i = 0; i < AES_BLOCK_SIZE; i++) {
+ dst[i] ^= src[i];
+ }
}
static void aes_ccm_auth_start(size_t M, size_t L, const uint8_t *nonce, const uint8_t *aad, size_t aad_len, size_t plain_len,
uint8_t *x)
diff --git a/src/mesh/http/ContentHelper.h b/src/mesh/http/ContentHelper.h
index a80c39f47..e5d3a2f57 100644
--- a/src/mesh/http/ContentHelper.h
+++ b/src/mesh/http/ContentHelper.h
@@ -1,5 +1,6 @@
#include
#include
+#include
#define BoolToString(x) ((x) ? "true" : "false")
diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp
index f9e5d1cc9..38aa2e2a2 100644
--- a/src/mesh/wifi/WiFiAPClient.cpp
+++ b/src/mesh/wifi/WiFiAPClient.cpp
@@ -430,4 +430,4 @@ uint8_t getWifiDisconnectReason()
{
return wifiDisconnectReason;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index 69b2c0a38..fc3b914e5 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -175,6 +175,12 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
LOG_INFO("Client set ham mode");
handleSetHamMode(r->set_ham_mode);
break;
+ case meshtastic_AdminMessage_get_ui_config_request_tag: {
+ LOG_INFO("Client is getting device-ui config");
+ handleGetDeviceUIConfig(mp);
+ handled = true;
+ break;
+ }
/**
* Other
@@ -234,6 +240,12 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
reboot(DEFAULT_REBOOT_SECONDS);
break;
}
+ case meshtastic_AdminMessage_store_ui_config_tag: {
+ LOG_INFO("Storing device-ui config");
+ handleStoreDeviceUIConfig(r->store_ui_config);
+ handled = true;
+ break;
+ }
case meshtastic_AdminMessage_begin_edit_settings_tag: {
LOG_INFO("Begin transaction for editing settings");
hasOpenEditTransaction = true;
@@ -477,7 +489,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER,
meshtastic_Config_DeviceConfig_Role_REPEATER)) {
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
- const char *warning = "Rebroadcast mode can't be set to NONE for a router or repeater\n";
+ const char *warning = "Rebroadcast mode can't be set to NONE for a router or repeater";
LOG_WARN(warning);
sendWarning(warning);
}
@@ -621,6 +633,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
requiresReboot = false;
break;
+ case meshtastic_Config_device_ui_tag:
+ // NOOP! This is handled by handleStoreDeviceUIConfig
+ break;
}
if (requiresReboot && !hasOpenEditTransaction) {
disableBluetooth();
@@ -783,6 +798,10 @@ void AdminModule::handleGetConfig(const meshtastic_MeshPacket &req, const uint32
LOG_INFO("Get config: Sessionkey");
res.get_config_response.which_payload_variant = meshtastic_Config_sessionkey_tag;
break;
+ case meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG:
+ // NOOP! This is handled by handleGetDeviceUIConfig
+ res.get_config_response.which_payload_variant = meshtastic_Config_device_ui_tag;
+ break;
}
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
@@ -995,6 +1014,14 @@ void AdminModule::handleGetChannel(const meshtastic_MeshPacket &req, uint32_t ch
}
}
+void AdminModule::handleGetDeviceUIConfig(const meshtastic_MeshPacket &req)
+{
+ meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default;
+ r.which_payload_variant = meshtastic_AdminMessage_get_ui_config_response_tag;
+ r.get_ui_config_response = uiconfig;
+ myReply = allocDataProtobuf(r);
+}
+
void AdminModule::reboot(int32_t seconds)
{
LOG_INFO("Reboot in %d seconds", seconds);
@@ -1015,6 +1042,11 @@ void AdminModule::saveChanges(int saveWhat, bool shouldReboot)
}
}
+void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg)
+{
+ nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uicfg);
+}
+
void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
{
// Set call sign and override lora limitations for licensed use
@@ -1081,7 +1113,7 @@ bool AdminModule::messageIsResponse(const meshtastic_AdminMessage *r)
r->which_payload_variant == meshtastic_AdminMessage_get_ringtone_response_tag ||
r->which_payload_variant == meshtastic_AdminMessage_get_device_connection_status_response_tag ||
r->which_payload_variant == meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag ||
- r->which_payload_variant == meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag)
+ r->which_payload_variant == meshtastic_AdminMessage_get_ui_config_response_tag)
return true;
else
return false;
@@ -1097,7 +1129,8 @@ bool AdminModule::messageIsRequest(const meshtastic_AdminMessage *r)
r->which_payload_variant == meshtastic_AdminMessage_get_device_metadata_request_tag ||
r->which_payload_variant == meshtastic_AdminMessage_get_ringtone_request_tag ||
r->which_payload_variant == meshtastic_AdminMessage_get_device_connection_status_request_tag ||
- r->which_payload_variant == meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag)
+ r->which_payload_variant == meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag ||
+ r->which_payload_variant == meshtastic_AdminMessage_get_ui_config_request_tag)
return true;
else
return false;
@@ -1123,4 +1156,4 @@ void disableBluetooth()
nrf52Bluetooth->shutdown();
#endif
#endif
-}
\ No newline at end of file
+}
diff --git a/src/modules/AdminModule.h b/src/modules/AdminModule.h
index b99e86707..ee2ebfd96 100644
--- a/src/modules/AdminModule.h
+++ b/src/modules/AdminModule.h
@@ -43,6 +43,7 @@ class AdminModule : public ProtobufModule, public Obser
void handleGetDeviceMetadata(const meshtastic_MeshPacket &req);
void handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &req);
void handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &req);
+ void handleGetDeviceUIConfig(const meshtastic_MeshPacket &req);
/**
* Setters
*/
@@ -52,6 +53,7 @@ class AdminModule : public ProtobufModule, public Obser
void handleSetModuleConfig(const meshtastic_ModuleConfig &c);
void handleSetChannel();
void handleSetHamMode(const meshtastic_HamParameters &req);
+ void handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg);
void reboot(int32_t seconds);
void setPassKey(meshtastic_AdminMessage *res);
diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h
index fd9ffc9b6..a91933a0f 100644
--- a/src/modules/CannedMessageModule.h
+++ b/src/modules/CannedMessageModule.h
@@ -117,8 +117,10 @@ class CannedMessageModule : public SinglePortModule, public ObservableshouldDraw(); }
virtual Observable *getUIFrameObservable() override { return this; }
- virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override;
virtual bool interceptingKeyboardInput() override;
+#if !HAS_TFT
+ virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override;
+#endif
virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response) override;
@@ -228,4 +230,4 @@ class CannedMessageModule : public SinglePortModule, public Observableinit();
#endif // INPUTBROKER_MATRIX_TYPE
#endif // HAS_BUTTON
-#if ARCH_PORTDUINO
+#if ARCH_PORTDUINO && !HAS_TFT
aLinuxInputImpl = new LinuxInputImpl();
aLinuxInputImpl->init();
#endif
@@ -195,11 +195,13 @@ void setupModules()
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first > 0) {
new AirQualityTelemetryModule();
}
+#if !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX30102].first > 0 ||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MLX90614].first > 0) {
new HealthTelemetryModule();
}
#endif
+#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
new PowerTelemetryModule();
#endif
@@ -245,4 +247,4 @@ void setupModules()
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
// acks
routingModule = new RoutingModule();
-}
+}
\ No newline at end of file
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index 92d964f7d..008da5c71 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -18,6 +18,7 @@
#include
#include
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
// Sensors
#include "Sensor/AHT10.h"
#include "Sensor/BME280Sensor.h"
@@ -36,7 +37,6 @@
#include "Sensor/SHT31Sensor.h"
#include "Sensor/SHT4XSensor.h"
#include "Sensor/SHTC3Sensor.h"
-#include "Sensor/T1000xSensor.h"
#include "Sensor/TSL2591Sensor.h"
#include "Sensor/VEML7700Sensor.h"
@@ -58,11 +58,12 @@ MLX90632Sensor mlx90632Sensor;
DFRobotLarkSensor dfRobotLarkSensor;
NAU7802Sensor nau7802Sensor;
BMP3XXSensor bmp3xxSensor;
+CGRadSensSensor cgRadSens;
+#endif
#ifdef T1000X_SENSOR_EN
+#include "Sensor/T1000xSensor.h"
T1000xSensor t1000xSensor;
#endif
-CGRadSensSensor cgRadSens;
-
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -104,7 +105,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
// therefore, we should only enable the sensor loop if measurement is also enabled
#ifdef T1000X_SENSOR_EN
result = t1000xSensor.runOnce();
-#else
+#elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
if (dfRobotLarkSensor.hasSensor())
result = dfRobotLarkSensor.runOnce();
if (bmp085Sensor.hasSensor())
@@ -159,8 +160,10 @@ int32_t EnvironmentTelemetryModule::runOnce()
if (!moduleConfig.telemetry.environment_measurement_enabled) {
return disable();
} else {
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
if (bme680Sensor.hasSensor())
result = bme680Sensor.runTrigger();
+#endif
}
if (((lastSentToMesh == 0) ||
@@ -499,6 +502,7 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
meshtastic_AdminMessage *response)
{
AdminMessageHandleResult result = AdminMessageHandleResult::NOT_HANDLED;
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
if (dfRobotLarkSensor.hasSensor()) {
result = dfRobotLarkSensor.handleAdminMessage(mp, request, response);
if (result != AdminMessageHandleResult::NOT_HANDLED)
@@ -609,7 +613,8 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
if (result != AdminMessageHandleResult::NOT_HANDLED)
return result;
}
+#endif
return result;
}
-#endif
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/HealthTelemetry.cpp b/src/modules/Telemetry/HealthTelemetry.cpp
index 22534e9f5..1b9b49813 100644
--- a/src/modules/Telemetry/HealthTelemetry.cpp
+++ b/src/modules/Telemetry/HealthTelemetry.cpp
@@ -1,6 +1,6 @@
#include "configuration.h"
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && !defined(ARCH_PORTDUINO)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "Default.h"
@@ -246,4 +246,4 @@ bool HealthTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
return false;
}
-#endif
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/HealthTelemetry.h b/src/modules/Telemetry/HealthTelemetry.h
index fe84f2d27..01e4c2372 100644
--- a/src/modules/Telemetry/HealthTelemetry.h
+++ b/src/modules/Telemetry/HealthTelemetry.h
@@ -1,6 +1,6 @@
#include "configuration.h"
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && !defined(ARCH_PORTDUINO)
#pragma once
#include "../mesh/generated/meshtastic/telemetry.pb.h"
@@ -57,4 +57,4 @@ class HealthTelemetryModule : private concurrency::OSThread, public ProtobufModu
uint32_t sensor_read_error_count = 0;
};
-#endif
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp b/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp
index 88128a6db..f99956925 100644
--- a/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp
+++ b/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp
@@ -1,6 +1,6 @@
#include "configuration.h"
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && !defined(ARCH_PORTDUINO)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "MAX30102Sensor.h"
@@ -80,4 +80,4 @@ bool MAX30102Sensor::getMetrics(meshtastic_Telemetry *measurement)
return true;
}
-#endif
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/MAX30102Sensor.h b/src/modules/Telemetry/Sensor/MAX30102Sensor.h
index 426d9d365..026e30ed0 100644
--- a/src/modules/Telemetry/Sensor/MAX30102Sensor.h
+++ b/src/modules/Telemetry/Sensor/MAX30102Sensor.h
@@ -1,6 +1,6 @@
#include "configuration.h"
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && !defined(ARCH_PORTDUINO)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
@@ -23,4 +23,4 @@ class MAX30102Sensor : public TelemetrySensor
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
};
-#endif
+#endif
\ No newline at end of file
diff --git a/src/motion/QMA6100PSensor.cpp b/src/motion/QMA6100PSensor.cpp
index 4c5bc14d2..eb81e16c7 100644
--- a/src/motion/QMA6100PSensor.cpp
+++ b/src/motion/QMA6100PSensor.cpp
@@ -88,13 +88,13 @@ bool QMA6100PSingleton::init(ScanI2C::FoundDevice device)
bool status = begin(device.address.address, &Wire);
#endif
if (status != true) {
- LOG_WARN("QMA6100P init begin failed\n");
+ LOG_WARN("QMA6100P init begin failed");
return false;
}
delay(20);
// SW reset to make sure the device starts in a known state
if (softwareReset() != true) {
- LOG_WARN("QMA6100P init reset failed\n");
+ LOG_WARN("QMA6100P init reset failed");
return false;
}
delay(20);
@@ -180,4 +180,4 @@ bool QMA6100PSingleton::setWakeOnMotion()
return true;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 1a274aa28..742b295b5 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -174,6 +174,8 @@
#define HW_VENDOR meshtastic_HardwareModel_SENSECAP_INDICATOR
#elif defined(SEEED_XIAO_S3)
#define HW_VENDOR meshtastic_HardwareModel_SEEED_XIAO_S3
+#elif defined(MESH_TAB)
+#define HW_VENDOR meshtastic_HardwareModel_MESH_TAB
#endif
// -----------------------------------------------------------------------------
diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp
index 82fd8de66..4fadc3ca9 100644
--- a/src/platform/portduino/PortduinoGlue.cpp
+++ b/src/platform/portduino/PortduinoGlue.cpp
@@ -153,6 +153,7 @@ void portduinoSetup()
std::string gpioChipName = "gpiochip";
settingsStrings[i2cdev] = "";
settingsStrings[keyboardDevice] = "";
+ settingsStrings[pointerDevice] = "";
settingsStrings[webserverrootpath] = "";
settingsStrings[spidev] = "";
settingsStrings[displayspidev] = "";
@@ -455,6 +456,8 @@ bool loadConfig(const char *configPath)
settingsMap[displayPanel] = ili9341;
else if (yamlConfig["Display"]["Panel"].as("") == "ILI9342")
settingsMap[displayPanel] = ili9342;
+ else if (yamlConfig["Display"]["Panel"].as("") == "ILI9486")
+ settingsMap[displayPanel] = ili9486;
else if (yamlConfig["Display"]["Panel"].as("") == "ILI9488")
settingsMap[displayPanel] = ili9488;
else if (yamlConfig["Display"]["Panel"].as("") == "HX8357D")
@@ -515,6 +518,7 @@ bool loadConfig(const char *configPath)
}
if (yamlConfig["Input"]) {
settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as("");
+ settingsStrings[pointerDevice] = (yamlConfig["Input"]["PointerDevice"]).as("");
}
if (yamlConfig["Webserver"]) {
@@ -570,4 +574,4 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac)
} else {
return false;
}
-}
\ No newline at end of file
+}
diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h
index 9cf9b6678..5bc07df6a 100644
--- a/src/platform/portduino/PortduinoGlue.h
+++ b/src/platform/portduino/PortduinoGlue.h
@@ -55,6 +55,7 @@ enum configNames {
displayOffsetY,
displayInvert,
keyboardDevice,
+ pointerDevice,
logoutputlevel,
traceFilename,
webserver,
@@ -66,7 +67,7 @@ enum configNames {
config_directory,
mac_address
};
-enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9488, hx8357d };
+enum { no_screen, x11, 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 };
diff --git a/variants/diy/platformio.ini b/variants/diy/platformio.ini
index b60d46996..b7f3f6a92 100644
--- a/variants/diy/platformio.ini
+++ b/variants/diy/platformio.ini
@@ -87,73 +87,3 @@ build_flags =
-D ARDUINO_USB_MODE=0
-D ARDUINO_USB_CDC_ON_BOOT=1
-I variants/diy/t-energy-s3_e22
-
-; esp32-s3 + ra-sh01 lora + 3.2" ILI9143
-[env:mesh-tab]
-extends = esp32s3_base
-board = um_feathers3
-board_level = extra
-board_upload.flash_size = 16MB
-board_build.partitions = default_16MB.csv
-upload_protocol = esptool
-build_flags = ${esp32s3_base.build_flags}
- -D MESH_TAB
- -D PRIVATE_HW
- -D CONFIG_ARDUHAL_ESP_LOG
- -D CONFIG_ARDUHAL_LOG_COLORS=1
- -D CONFIG_DISABLE_HAL_LOCKS=1 ; "feels" to be a bit more stable without locks
- -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
- -D MESHTASTIC_EXCLUDE_INPUTBROKER=1
- -D MESHTASTIC_EXCLUDE_BLUETOOTH=1
- -D MESHTASTIC_EXCLUDE_WEBSERVER=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 MAX_NUM_NODES=250
- -D MAX_THREADS=40
- -D HAS_SCREEN=0
- -D HAS_TFT=1
- -D RAM_SIZE=1024
- -D LGFX_DRIVER_TEMPLATE
- -D LGFX_DRIVER=LGFX_GENERIC
- -D LGFX_PANEL=ILI9341
- -D LGFX_OFFSET_ROTATION=1
- -D LGFX_TOUCH=XPT2046
- -D LGFX_PIN_SCK=12
- -D LGFX_PIN_MOSI=13
- -D LGFX_PIN_MISO=11
- -D LGFX_PIN_DC=16
- -D LGFX_PIN_CS=10
- -D LGFX_PIN_RST=-1
- -D LGFX_PIN_BL=42
- -D LGFX_TOUCH_INT=41
- -D LGFX_TOUCH_CS=7
- -D LGFX_TOUCH_CLK=12
- -D LGFX_TOUCH_DO=11
- -D LGFX_TOUCH_DIN=13
- -D LGFX_TOUCH_X_MIN=300
- -D LGFX_TOUCH_X_MAX=3900
- -D LGFX_TOUCH_Y_MIN=400
- -D LGFX_TOUCH_Y_MAX=3900
- -D VIEW_320x240
- -D USE_PACKET_API
- -I lib/device-ui/generated/ui_320x240
- -I variants/diy/mesh-tab
-build_src_filter = ${esp32_base.build_src_filter}
- +<../lib/device-ui/generated/ui_320x240>
- +<../lib/device-ui/resources>
- +<../lib/device-ui/locale>
- +<../lib/device-ui/source>
-lib_deps = ${esp32_base.lib_deps}
- lovyan03/LovyanGFX@^1.1.16
- earlephilhower/ESP8266Audio@^1.9.7
- earlephilhower/ESP8266SAM@^1.0.1
\ No newline at end of file
diff --git a/variants/mesh-tab/pins_arduino.h b/variants/mesh-tab/pins_arduino.h
new file mode 100644
index 000000000..c995f638c
--- /dev/null
+++ b/variants/mesh-tab/pins_arduino.h
@@ -0,0 +1,65 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include "soc/soc_caps.h"
+#include
+
+#define USB_VID 0x303A
+#define USB_PID 0x80D6
+
+static const uint8_t TX = 43;
+static const uint8_t RX = 44;
+
+static const uint8_t SDA = 8;
+static const uint8_t SCL = 9;
+
+static const uint8_t SS = 5;
+static const uint8_t MOSI = 35;
+static const uint8_t MISO = 37;
+static const uint8_t SDO = 35;
+static const uint8_t SDI = 37;
+static const uint8_t SCK = 36;
+
+static const uint8_t A0 = 1;
+static const uint8_t A1 = 2;
+static const uint8_t A2 = 3;
+static const uint8_t A3 = 4;
+static const uint8_t A4 = 5;
+static const uint8_t A5 = 6;
+static const uint8_t A6 = 7;
+static const uint8_t A7 = 8;
+static const uint8_t A8 = 9;
+static const uint8_t A9 = 10;
+static const uint8_t A10 = 11;
+static const uint8_t A11 = 12;
+static const uint8_t A12 = 13;
+
+static const uint8_t T1 = 1;
+static const uint8_t T3 = 3;
+static const uint8_t T5 = 5;
+static const uint8_t T6 = 6;
+static const uint8_t T7 = 7;
+static const uint8_t T8 = 8;
+static const uint8_t T9 = 9;
+static const uint8_t T10 = 10;
+static const uint8_t T11 = 11;
+static const uint8_t T12 = 12;
+static const uint8_t T14 = 14;
+
+static const uint8_t VBAT_SENSE = 2;
+static const uint8_t VBUS_SENSE = 34;
+
+// User LED
+#define LED_BUILTIN 13
+#define BUILTIN_LED LED_BUILTIN // backward compatibility
+
+static const uint8_t RGB_DATA = 40;
+// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite()
+#define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT)
+#define RGB_BRIGHTNESS 64
+
+static const uint8_t RGB_PWR = 39;
+static const uint8_t LDO2 = 39;
+static const uint8_t LED = 13;
+
+#endif /* Pins_Arduino_h */
diff --git a/variants/mesh-tab/platformio.ini b/variants/mesh-tab/platformio.ini
new file mode 100644
index 000000000..26b072cde
--- /dev/null
+++ b/variants/mesh-tab/platformio.ini
@@ -0,0 +1,233 @@
+; Base for Mesh-Tab device (esp32-s3 N16R2 + ra-sh01 lora)
+; https://github.com/valzzu/Mesh-Tab
+[mesh_tab_base]
+extends = esp32s3_base
+board = mesh-tab
+board_level = extra
+board_upload.flash_size = 16MB
+board_build.partitions = default_16MB.csv
+upload_protocol = esptool
+build_flags = ${esp32s3_base.build_flags}
+ -D MESH_TAB
+ -D CONFIG_ARDUHAL_ESP_LOG
+ -D CONFIG_ARDUHAL_LOG_COLORS=1
+ -D CONFIG_DISABLE_HAL_LOCKS=1
+ -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
+ -D MESHTASTIC_EXCLUDE_INPUTBROKER=1
+ -D MESHTASTIC_EXCLUDE_BLUETOOTH=1
+ -D MESHTASTIC_EXCLUDE_WEBSERVER=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 MAX_NUM_NODES=250
+ -D MAX_THREADS=40
+ -D HAS_SCREEN=0
+ -D HAS_TFT=1
+ -D USE_PIN_BUZZER
+ -D RAM_SIZE=1024
+ -D LGFX_DRIVER_TEMPLATE
+ -D LGFX_DRIVER=LGFX_GENERIC
+ -D LGFX_PIN_SCK=12
+ -D LGFX_PIN_MOSI=13
+ -D LGFX_PIN_MISO=11
+ -D LGFX_PIN_DC=16
+ -D LGFX_PIN_CS=10
+ -D LGFX_PIN_RST=-1
+ -D LGFX_PIN_BL=42
+ -D LGFX_TOUCH_INT=41
+ -D VIEW_320x240
+ -D USE_PACKET_API
+ -I lib/device-ui/generated/ui_320x240
+ -I variants/mesh-tab
+build_src_filter = ${esp32_base.build_src_filter}
+ +<../lib/device-ui/generated/ui_320x240>
+ +<../lib/device-ui/resources>
+ +<../lib/device-ui/locale>
+ +<../lib/device-ui/source>
+lib_deps = ${esp32_base.lib_deps}
+ lovyan03/LovyanGFX@^1.1.16
+
+; 3.2" TN TFT ST7789 / XPT2046: https://vi.aliexpress.com/item/1005005933490544.html
+[env:mesh-tab-3-2-TN-resistive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D LGFX_SCREEN_WIDTH=240
+ -D LGFX_SCREEN_HEIGHT=320
+ -D LGFX_PANEL=ST7789
+ -D LGFX_INVERT_COLOR=false
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_ROTATION=3
+ -D LGFX_TOUCH=XPT2046
+ -D SPI_FREQUENCY=60000000
+ -D LGFX_TOUCH_SPI_FREQ=2500000
+ -D LGFX_TOUCH_SPI_HOST=2
+ -D LGFX_TOUCH_CS=7
+ -D LGFX_TOUCH_CLK=12
+ -D LGFX_TOUCH_DO=11
+ -D LGFX_TOUCH_DIN=13
+ -D LGFX_TOUCH_X_MIN=300
+ -D LGFX_TOUCH_X_MAX=3900
+ -D LGFX_TOUCH_Y_MIN=400
+ -D LGFX_TOUCH_Y_MAX=3900
+ -D LGFX_TOUCH_ROTATION=4
+
+; 3.2" IPS TFT ILI9341 / XPT2046: https://www.aliexpress.com/item/1005006258575617.html
+[env:mesh-tab-3-2-IPS-resistive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D LGFX_SCREEN_WIDTH=240
+ -D LGFX_SCREEN_HEIGHT=320
+ -D LGFX_PANEL=ILI9341
+ -D LGFX_INVERT_COLOR=true
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_ROTATION=1
+ -D LGFX_TOUCH=XPT2046
+ -D SPI_FREQUENCY=60000000 ; if image is distorted then lower to 40 MHz
+ -D LGFX_TOUCH_SPI_FREQ=2500000
+ -D LGFX_TOUCH_SPI_HOST=2
+ -D LGFX_TOUCH_CS=7
+ -D LGFX_TOUCH_CLK=12
+ -D LGFX_TOUCH_DO=11
+ -D LGFX_TOUCH_DIN=13
+ -D LGFX_TOUCH_X_MIN=300
+ -D LGFX_TOUCH_X_MAX=3900
+ -D LGFX_TOUCH_Y_MIN=400
+ -D LGFX_TOUCH_Y_MAX=3900
+ -D LGFX_TOUCH_ROTATION=4
+
+; 3.5" IPS TFT ILI9488 / XPT2046: https://vi.aliexpress.com/item/1005006333922639.html
+[env:mesh-tab-3-5-IPS-resistive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D DISPLAY_SET_RESOLUTION
+ -D LGFX_SCREEN_WIDTH=320
+ -D LGFX_SCREEN_HEIGHT=480
+ -D LGFX_PANEL=ILI9488
+ -D LGFX_INVERT_COLOR=true
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_DLEN_16BITS=false
+ -D LGFX_ROTATION=0
+ -D LGFX_TOUCH=XPT2046
+ -D SPI_FREQUENCY=40000000 ; may go higher upto 40/60/80 MHz
+ -D LGFX_TOUCH_SPI_FREQ=2500000
+ -D LGFX_TOUCH_SPI_HOST=2
+ -D LGFX_TOUCH_CS=7
+ -D LGFX_TOUCH_CLK=12
+ -D LGFX_TOUCH_DO=11
+ -D LGFX_TOUCH_DIN=13
+ -D LGFX_TOUCH_X_MIN=300
+ -D LGFX_TOUCH_X_MAX=3900
+ -D LGFX_TOUCH_Y_MIN=400
+ -D LGFX_TOUCH_Y_MAX=3900
+ -D LGFX_TOUCH_ROTATION=0
+
+; 3.5" TN TFT ILI9488 / XPT2046: https://vi.aliexpress.com/item/32985467436.html
+[env:mesh-tab-3-5-TN-resistive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D DISPLAY_SET_RESOLUTION
+ -D LGFX_SCREEN_WIDTH=320
+ -D LGFX_SCREEN_HEIGHT=480
+ -D LGFX_PANEL=HX8357B
+ -D SPI_FREQUENCY=60000000
+ -D LGFX_INVERT_COLOR=false
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_DLEN_16BITS=false
+ -D LGFX_ROTATION=4
+ -D LGFX_TOUCH=XPT2046
+ -D LGFX_TOUCH_SPI_FREQ=2500000
+ -D LGFX_TOUCH_SPI_HOST=2
+ -D LGFX_TOUCH_CS=7
+ -D LGFX_TOUCH_CLK=12
+ -D LGFX_TOUCH_DO=11
+ -D LGFX_TOUCH_DIN=13
+ -D LGFX_TOUCH_X_MIN=300
+ -D LGFX_TOUCH_X_MAX=3900
+ -D LGFX_TOUCH_Y_MIN=400
+ -D LGFX_TOUCH_Y_MAX=3900
+ -D LGFX_TOUCH_ROTATION=2
+
+; 3.2" IPS TFT ILI9341 / FT6236: https://vi.aliexpress.com/item/1005006624072350.html
+[env:mesh-tab-3-2-IPS-capacitive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D LGFX_SCREEN_WIDTH=240
+ -D LGFX_SCREEN_HEIGHT=320
+ -D LGFX_PANEL=ILI9341
+ -D LGFX_INVERT_COLOR=true
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_ROTATION=1
+ -D LGFX_TOUCH=FT5x06
+ -D SPI_FREQUENCY=40000000 ; may go higher upto 60/80 MHz
+ -D LGFX_TOUCH_I2C_PORT=0
+ -D LGFX_TOUCH_I2C_ADDR=0x38
+ -D LGFX_TOUCH_I2C_SDA=8
+ -D LGFX_TOUCH_I2C_SCL=9
+ -D LGFX_TOUCH_RST=7
+ -D LGFX_TOUCH_X_MIN=0
+ -D LGFX_TOUCH_X_MAX=319
+ -D LGFX_TOUCH_Y_MIN=0
+ -D LGFX_TOUCH_Y_MAX=479
+ -D LGFX_TOUCH_ROTATION=0
+ -D LGFX_TOUCH_I2C_FREQ=1000000
+
+; 3.5" IPS TFT ILI9488 / FT6236: https://vi.aliexpress.com/item/1005006893699919.html
+[env:mesh-tab-3-5-IPS-capacitive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D DISPLAY_SET_RESOLUTION
+ -D LGFX_SCREEN_WIDTH=320
+ -D LGFX_SCREEN_HEIGHT=480
+ -D LGFX_PANEL=ILI9488
+ -D LGFX_INVERT_COLOR=true
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_DLEN_16BITS=false
+ -D LGFX_ROTATION=1
+ -D LGFX_TOUCH=FT5x06
+ -D SPI_FREQUENCY=30000000 ; may go higher upto 40/60/80 MHz
+ -D LGFX_TOUCH_I2C_PORT=0
+ -D LGFX_TOUCH_I2C_ADDR=0x38
+ -D LGFX_TOUCH_I2C_SDA=8
+ -D LGFX_TOUCH_I2C_SCL=9
+ -D LGFX_TOUCH_RST=7
+ -D LGFX_TOUCH_X_MIN=0
+ -D LGFX_TOUCH_X_MAX=319
+ -D LGFX_TOUCH_Y_MIN=0
+ -D LGFX_TOUCH_Y_MAX=479
+ -D LGFX_TOUCH_ROTATION=1
+ -D LGFX_TOUCH_I2C_FREQ=1000000
+
+; 4.0" IPS TFT ILI9488 / FT6236: https://vi.aliexpress.com/item/1005007082906950.html
+[env:mesh-tab-4-0-IPS-capacitive]
+extends = mesh_tab_base
+build_flags = ${mesh_tab_base.build_flags}
+ -D DISPLAY_SET_RESOLUTION
+ -D LGFX_SCREEN_WIDTH=320
+ -D LGFX_SCREEN_HEIGHT=480
+ -D LGFX_PANEL=HX8357B
+ -D LGFX_INVERT_COLOR=true
+ -D LGFX_RGB_ORDER=false
+ -D LGFX_DLEN_16BITS=false
+ -D LGFX_ROTATION=4
+ -D LGFX_TOUCH=FT5x06
+ -D SPI_FREQUENCY=30000000 ; may go higher upto 40/60/80 MHz
+ -D LGFX_TOUCH_I2C_PORT=0
+ -D LGFX_TOUCH_I2C_ADDR=0x38
+ -D LGFX_TOUCH_I2C_SDA=8
+ -D LGFX_TOUCH_I2C_SCL=9
+ -D LGFX_TOUCH_RST=7
+ -D LGFX_TOUCH_X_MIN=0
+ -D LGFX_TOUCH_X_MAX=319
+ -D LGFX_TOUCH_Y_MIN=0
+ -D LGFX_TOUCH_Y_MAX=479
+ -D LGFX_TOUCH_ROTATION=1
+ -D LGFX_TOUCH_I2C_FREQ=1000000
\ No newline at end of file
diff --git a/variants/diy/mesh-tab/variant.h b/variants/mesh-tab/variant.h
similarity index 67%
rename from variants/diy/mesh-tab/variant.h
rename to variants/mesh-tab/variant.h
index 0a23a3c36..533c931bc 100644
--- a/variants/diy/mesh-tab/variant.h
+++ b/variants/mesh-tab/variant.h
@@ -7,8 +7,8 @@
// Analog pins
#define BATTERY_PIN 4 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
-// ratio of voltage divider = 2.0
-#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage.
+// ratio of voltage divider (100k, 220k)
+#define ADC_MULTIPLIER 1.6 // 1.45 + 10% for correction of display undervoltage.
#define ADC_CHANNEL ADC1_GPIO4_CHANNEL
// LED
@@ -17,6 +17,9 @@
// Button
#define BUTTON_PIN 0
+// Button
+#define PIN_BUZZER 5
+
// GPS
#define GPS_RX_PIN 18
#define GPS_TX_PIN 17
@@ -28,20 +31,26 @@
#define SPI_CS 10
#define SDCARD_CS 6
+// LORA MODULES
+#define USE_SX1262
+
// LORA SPI
#define LORA_SCK 36
#define LORA_MISO 37
#define LORA_MOSI 35
#define LORA_CS 39
-// LORA MODULES
-#define USE_SX1262
-
// LORA CONFIG
+#define LORA_DIO0 -1 // a No connect on the SX1262 module
+#define LORA_RESET 14
+#define LORA_DIO1 15 // SX1262 IRQ
+#define LORA_DIO2 40 // SX1262 BUSY
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262
+
#define SX126X_CS LORA_CS
-#define SX126X_DIO1 15
+#define SX126X_DIO1 LORA_DIO1
#define SX126X_DIO2_AS_RF_SWITCH
-#define SX126X_BUSY 40
+#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET 14
#define SX126X_RXEN 47
#define SX126X_TXEN RADIOLIB_NC // Assuming that DIO2 is connected to TXEN pin
diff --git a/variants/rak2560/RAK9154Sensor.cpp b/variants/rak2560/RAK9154Sensor.cpp
index 9f660947e..43affe581 100644
--- a/variants/rak2560/RAK9154Sensor.cpp
+++ b/variants/rak2560/RAK9154Sensor.cpp
@@ -37,11 +37,11 @@ static void onewire_evt(const uint8_t pid, const uint8_t sid, const SNHUBAPI_EVT
break;
case SNHUBAPI_EVT_ADD_SID:
- // LOG_INFO("+ADD:SID:[%02x]\r\n", msg[0]);
+ // LOG_INFO("+ADD:SID:[%02x]", msg[0]);
break;
case SNHUBAPI_EVT_ADD_PID:
- // LOG_INFO("+ADD:PID:[%02x]\r\n", msg[0]);
+ // LOG_INFO("+ADD:PID:[%02x]", msg[0]);
#ifdef BOOT_DATA_REQ
provision = msg[0];
#endif
@@ -55,12 +55,12 @@ static void onewire_evt(const uint8_t pid, const uint8_t sid, const SNHUBAPI_EVT
case SNHUBAPI_EVT_SDATA_REQ:
- // LOG_INFO("+EVT:PID[%02x],IPSO[%02x]\r\n",pid,msg[0]);
+ // LOG_INFO("+EVT:PID[%02x],IPSO[%02x]",pid,msg[0]);
// for( uint16_t i=1; i 0) ? true : false;
}
-#endif // HAS_RAKPROT
\ No newline at end of file
+#endif // HAS_RAKPROT
diff --git a/variants/tracker-t1000-e/platformio.ini b/variants/tracker-t1000-e/platformio.ini
index 075811610..0bce9fbb5 100644
--- a/variants/tracker-t1000-e/platformio.ini
+++ b/variants/tracker-t1000-e/platformio.ini
@@ -4,6 +4,7 @@ board = tracker-t1000-e
build_flags = ${nrf52840_base.build_flags} -Ivariants/tracker-t1000-e -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DTRACKER_T1000_E
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE
+ -DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL=1
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/tracker-t1000-e>
lib_deps =
@@ -11,4 +12,4 @@ lib_deps =
https://github.com/meshtastic/QMA6100P_Arduino_Library.git#14c900b8b2e4feaac5007a7e41e0c1b7f0841136
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
-upload_protocol = nrfutil
+upload_protocol = nrfutil
\ No newline at end of file
diff --git a/variants/unphone/pins_arduino.h b/variants/unphone/pins_arduino.h
index c4e9add1c..74067359f 100644
--- a/variants/unphone/pins_arduino.h
+++ b/variants/unphone/pins_arduino.h
@@ -6,14 +6,6 @@
#define USB_VID 0x16D0
#define USB_PID 0x1178
-#define EXTERNAL_NUM_INTERRUPTS 46
-#define NUM_DIGITAL_PINS 48
-#define NUM_ANALOG_INPUTS 20
-
-#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
-#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1)
-#define digitalPinHasPWM(p) (p < 46)
-
#define LED_BUILTIN 13
#define BUILTIN_LED LED_BUILTIN // backward compatibility