mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-22 02:32:23 +00:00
Compare commits
34 Commits
multicast-
...
v2.6.3.d28
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6429eca5e4 | ||
|
|
13101c1bab | ||
|
|
d28af68b5a | ||
|
|
53a7afff41 | ||
|
|
eb375d8e62 | ||
|
|
33f2b7144f | ||
|
|
e5f8218d34 | ||
|
|
0ddb507055 | ||
|
|
3afe84c4f4 | ||
|
|
e9d8a3d7f9 | ||
|
|
e722a97987 | ||
|
|
daa4186d65 | ||
|
|
1ee800e901 | ||
|
|
cf7f0f9d08 | ||
|
|
1e4a0134e6 | ||
|
|
0951fdd49b | ||
|
|
848a3ed6a1 | ||
|
|
fd7a1f2ccb | ||
|
|
5acaf8f897 | ||
|
|
cff93adb5e | ||
|
|
e4d3ec1f59 | ||
|
|
ae27aaaf43 | ||
|
|
31c0e8fa2c | ||
|
|
0d95b1afcc | ||
|
|
46235f6f8b | ||
|
|
d1068fd1e4 | ||
|
|
f41afb14b1 | ||
|
|
f8ad02aab3 | ||
|
|
077759e15d | ||
|
|
22aa2d7582 | ||
|
|
6673cb9292 | ||
|
|
8efc9702d3 | ||
|
|
2876eec7ed | ||
|
|
9cc13e628a |
9
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
9
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -72,6 +72,15 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: mui
|
||||
attributes:
|
||||
label: Is this bug report about any UI component firmware like InkHUD or Meshtatic UI (MUI)?
|
||||
options:
|
||||
- label: Meshtastic UI aka MUI colorTFT
|
||||
- label: InkHUD ePaper
|
||||
- label: OLED slide UI on any display
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
|
||||
2
.github/actions/setup-base/action.yml
vendored
2
.github/actions/setup-base/action.yml
vendored
@@ -20,7 +20,7 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get -y update --fix-missing
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev libuv1-dev lsb-release
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
@@ -9,14 +9,14 @@ plugins:
|
||||
lint:
|
||||
enabled:
|
||||
- prettier@3.5.3
|
||||
- trufflehog@3.88.17
|
||||
- yamllint@1.36.0
|
||||
- trufflehog@3.88.18
|
||||
- yamllint@1.36.2
|
||||
- bandit@1.8.3
|
||||
- checkov@3.2.386
|
||||
- checkov@3.2.390
|
||||
- terrascan@1.19.9
|
||||
- trivy@0.60.0
|
||||
- taplo@0.9.3
|
||||
- ruff@0.10.0
|
||||
- ruff@0.11.1
|
||||
- isort@6.0.1
|
||||
- markdownlint@0.44.0
|
||||
- oxipng@9.1.4
|
||||
|
||||
@@ -17,7 +17,6 @@ build_flags =
|
||||
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
|
||||
-DMESHTASTIC_EXCLUDE_AUDIO=1
|
||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
||||
-DMAX_NUM_NODES=80
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
|
||||
[portduino_base]
|
||||
platform = https://github.com/Jorropo/platform-native.git#17fa89daec4402af491512f75278a7fec8a5818c
|
||||
platform = https://github.com/meshtastic/platform-native.git#e82ba1a19b6cd1dc55cbde29b33ea8dd0640014f
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
[stm32_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/ststm32
|
||||
platform_packages = platformio/framework-arduinoststm32@^4.20900.0
|
||||
platform = ststm32
|
||||
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32.git#2.9.0
|
||||
extra_scripts =
|
||||
${env.extra_scripts}
|
||||
post:extra_scripts/extra_stm32.py
|
||||
|
||||
build_type = release
|
||||
|
||||
;board_build.flash_offset = 0x08000000
|
||||
|
||||
build_flags =
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-flto
|
||||
-Isrc/platform/stm32wl -g
|
||||
@@ -18,27 +19,24 @@ build_flags =
|
||||
-DMESHTASTIC_EXCLUDE_SCREEN
|
||||
-DMESHTASTIC_EXCLUDE_MQTT
|
||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
-DMESHTASTIC_EXCLUDE_PKI
|
||||
-DMESHTASTIC_EXCLUDE_GPS
|
||||
; -DVECT_TAB_OFFSET=0x08000000
|
||||
-DconfigUSE_CMSIS_RTOS_V2=1
|
||||
; -DSPI_MODE_0=SPI_MODE0
|
||||
;-DDEBUG_MUTE
|
||||
-fmerge-all-constants
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
|
||||
build_src_filter =
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
|
||||
|
||||
board_upload.offset_address = 0x08000000
|
||||
upload_protocol = stlink
|
||||
debug_tool = stlink
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
charlesbaynham/OSFS@^1.2.3
|
||||
jgromes/RadioLib@7.0.2
|
||||
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
|
||||
${radiolib_base.lib_deps}
|
||||
https://github.com/caveman99/Crypto.git#eae9c768054118a9399690f8af202853d1ae8516
|
||||
|
||||
lib_ignore =
|
||||
mathertel/OneButton@2.6.1
|
||||
Wire
|
||||
Wire
|
||||
|
||||
17
bin/config.d/lora-usb-meshtoad-e22.yaml
Normal file
17
bin/config.d/lora-usb-meshtoad-e22.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 0
|
||||
IRQ: 6
|
||||
Reset: 2
|
||||
Busy: 4
|
||||
RXen: 1
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
spidev: ch341
|
||||
USB_PID: 0x5512
|
||||
USB_VID: 0x1A86
|
||||
# Optional: Reduce power to 10 dBm to
|
||||
# avoid over-drawing the USB port
|
||||
# SX126X_MAX_POWER: 10
|
||||
# Optional: Set the serial number for multi-radio support
|
||||
# USB_Serialnum: 13374201
|
||||
@@ -7,12 +7,19 @@ SET "DEBUG=0"
|
||||
SET "PYTHON="
|
||||
SET "WEB_APP=0"
|
||||
SET "TFT_BUILD=0"
|
||||
SET "TFT8=0"
|
||||
SET "TFT16=0"
|
||||
SET "BIGDB8=0"
|
||||
SET "BIGDB16=0"
|
||||
SET "ESPTOOL_BAUD=115200"
|
||||
SET "ESPTOOL_CMD="
|
||||
SET "LOGCOUNTER=0"
|
||||
|
||||
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable.
|
||||
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
|
||||
SET "C3=esp32c3"
|
||||
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
|
||||
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
|
||||
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3"
|
||||
|
||||
GOTO getopts
|
||||
:help
|
||||
ECHO Flash image file to device, but first erasing and writing system information.
|
||||
@@ -34,7 +41,7 @@ ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.bin -p COM11 --web
|
||||
GOTO eof
|
||||
|
||||
:version
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.0]
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.1]
|
||||
ECHO Meshtastic
|
||||
GOTO eof
|
||||
|
||||
@@ -106,7 +113,7 @@ IF NOT "__%PYTHON%__"=="____" (
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||
!ESPTOOL_CMD! >nul 2>&1
|
||||
IF %ERRORLEVEL% GTR 2 (
|
||||
IF %ERRORLEVEL% GEQ 2 (
|
||||
@REM esptool exits with code 1 if help is displayed.
|
||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||
EXIT /B 1
|
||||
@@ -121,6 +128,7 @@ CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!"
|
||||
IF "__!ESPTOOL_PORT!__" == "____" (
|
||||
CALL :LOG_MESSAGE WARN "Using esptool port: UNSET."
|
||||
) ELSE (
|
||||
SET "ESPTOOL_CMD=!ESPTOOL_CMD! --port !ESPTOOL_PORT!"
|
||||
CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!."
|
||||
)
|
||||
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
@@ -133,44 +141,36 @@ IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE ERROR "Cannot enable WebUI (--web) and MUI." & GOTO eof
|
||||
)
|
||||
SET "TFT_BUILD=1"
|
||||
GOTO tft
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *-tft-* file. !FILENAME!"
|
||||
GOTO no_tft
|
||||
)
|
||||
|
||||
:tft
|
||||
SET "TFT8MB=picomputer-s3 unphone seeed-sensecap-indicator"
|
||||
FOR %%a IN (%TFT8MB%) DO (
|
||||
FOR %%a IN (%BIGDB_8MB%) DO (
|
||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||
@REM We are working with any of %TFT8MB%.
|
||||
SET "TFT8=1"
|
||||
GOTO end_loop_tft8mb
|
||||
@REM We are working with any of %BIGDB_8MB%.
|
||||
SET "BIGDB8=1"
|
||||
GOTO end_loop_bigdb_8mb
|
||||
)
|
||||
)
|
||||
:end_loop_tft8mb
|
||||
:end_loop_bigdb_8mb
|
||||
|
||||
SET "TFT16MB=t-deck"
|
||||
FOR %%a IN (%TFT16MB%) DO (
|
||||
FOR %%a IN (%BIGDB_16MB%) DO (
|
||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||
@REM We are working with any of %TFT16MB%.
|
||||
SET "TFT16=1"
|
||||
GOTO end_loop_tft16mb
|
||||
@REM We are working with any of %BIGDB_16MB%.
|
||||
SET "BIGDB16=1"
|
||||
GOTO end_loop_bigdb_16mb
|
||||
)
|
||||
)
|
||||
:end_loop_tft16mb
|
||||
:end_loop_bigdb_16mb
|
||||
|
||||
IF %TFT8% EQU 1 CALL :LOG_MESSAGE INFO "tft and MUI 8mb selected."
|
||||
IF %TFT16% EQU 1 CALL :LOG_MESSAGE INFO "tft and MUI 16mb selected."
|
||||
|
||||
:no_tft
|
||||
IF %BIGDB8% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 8mb partition selected."
|
||||
IF %BIGDB16% EQU 1 CALL :LOG_MESSAGE INFO "BigDB 16mb partition selected."
|
||||
|
||||
@REM Extract BASENAME from %FILENAME% for later use.
|
||||
SET "BASENAME=!FILENAME:firmware-=!"
|
||||
CALL :LOG_MESSAGE DEBUG "Computed firmware basename: !BASENAME!"
|
||||
|
||||
@REM Account for S3 and C3 board's different OTA partition.
|
||||
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
|
||||
FOR %%a IN (%S3%) DO (
|
||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||
@REM We are working with any of %S3%.
|
||||
@@ -179,7 +179,6 @@ FOR %%a IN (%S3%) DO (
|
||||
)
|
||||
)
|
||||
|
||||
SET "C3=esp32c3"
|
||||
FOR %%a IN (%C3%) DO (
|
||||
IF NOT "!FILENAME:%%a=!"=="!FILENAME!" (
|
||||
@REM We are working with any of %C3%.
|
||||
@@ -208,14 +207,14 @@ CALL :LOG_MESSAGE DEBUG "Set SPIFFS_FILENAME to: !SPIFFS_FILENAME!"
|
||||
SET "OTA_OFFSET=0x260000"
|
||||
SET "SPIFFS_OFFSET=0x300000"
|
||||
|
||||
@REM Offsets for MUI 8mb.
|
||||
IF %TFT8% EQU 1 IF %TFT_BUILD% EQU 1 (
|
||||
@REM Offsets for BigDB 8mb.
|
||||
IF %BIGDB8% EQU 1 (
|
||||
SET "OTA_OFFSET=0x340000"
|
||||
SET "SPIFFS_OFFSET=0x670000"
|
||||
)
|
||||
|
||||
@REM Offsets for MUI 16mb.
|
||||
IF %TFT16% EQU 1 IF %TFT_BUILD% EQU 1 (
|
||||
@REM Offsets for BigDB 16mb.
|
||||
IF %BIGDB16% EQU 1 (
|
||||
SET "OTA_OFFSET=0x650000"
|
||||
SET "SPIFFS_OFFSET=0xc90000"
|
||||
)
|
||||
|
||||
@@ -2,9 +2,48 @@
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
|
||||
WEB_APP=false
|
||||
TFT8=false
|
||||
TFT16=false
|
||||
TFT_BUILD=false
|
||||
MCU=""
|
||||
|
||||
# Variant groups
|
||||
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"
|
||||
)
|
||||
BIGDB_16MB=(
|
||||
"t-deck"
|
||||
"mesh-tab"
|
||||
"t-energy-s3"
|
||||
"dreamcatcher"
|
||||
"ESP32-S3-Pico"
|
||||
"m5stack-cores3"
|
||||
"station-g2"
|
||||
"t-eth-elite"
|
||||
"t-watch-s3"
|
||||
)
|
||||
S3_VARIANTS=(
|
||||
"s3"
|
||||
"-v3"
|
||||
"t-deck"
|
||||
"wireless-paper"
|
||||
"wireless-tracker"
|
||||
"station-g2"
|
||||
"unphone"
|
||||
)
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
@@ -42,8 +81,8 @@ while [ $# -gt 0 ]; do
|
||||
exit 0
|
||||
;;
|
||||
-p)
|
||||
ESPTOOL_PORT="$2"
|
||||
shift # Shift past the option argument
|
||||
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
|
||||
shift
|
||||
;;
|
||||
-P)
|
||||
PYTHON="$2"
|
||||
@@ -78,21 +117,13 @@ if [[ $FILENAME != firmware-* ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if FILENAME contains "-tft-" and set target partitionScheme accordingly.
|
||||
# Check if FILENAME contains "-tft-" and prevent web/mui comingling.
|
||||
if [[ ${FILENAME//-tft-/} != "$FILENAME" ]]; then
|
||||
TFT_BUILD=true
|
||||
if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
|
||||
echo "Cannot enable WebUI (--web) and MUI."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $FILENAME == *"picomputer-s3"* || $FILENAME == *"unphone"* || $FILENAME == *"seeed-sensecap-indicator"* ]]; then
|
||||
TFT8=true
|
||||
fi
|
||||
|
||||
if [[ $FILENAME == *"t-deck"* ]]; then
|
||||
TFT16=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract BASENAME from %FILENAME% for later use.
|
||||
@@ -105,20 +136,31 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
# Default OTA Offset
|
||||
OTA_OFFSET=0x260000
|
||||
|
||||
# littlefs* offset for MUI 8mb and OTA OFFSET.
|
||||
if [ "$TFT8" = true ] && [ "$TFT_BUILD" = true ]; then
|
||||
OFFSET=0x670000
|
||||
OTA_OFFSET=0x340000
|
||||
fi
|
||||
# littlefs* offset for BigDB 8mb and OTA OFFSET.
|
||||
for variant in "${BIGDB_8MB[@]}"; do
|
||||
if [ -n "${FILENAME##*"$variant"*}" ]; then
|
||||
OFFSET=0x670000
|
||||
OTA_OFFSET=0x340000
|
||||
fi
|
||||
done
|
||||
|
||||
# littlefs* offset for MUI 16mb and OTA OFFSET.
|
||||
if [ "$TFT16" = true ] && [ "$TFT_BUILD" = true ]; then
|
||||
OFFSET=0xc90000
|
||||
OTA_OFFSET=0x650000
|
||||
fi
|
||||
# littlefs* offset for BigDB 16mb and OTA OFFSET.
|
||||
for variant in "${BIGDB_16MB[@]}"; do
|
||||
if [ -n "${FILENAME##*"$variant"*}" ]; then
|
||||
OFFSET=0xc90000
|
||||
OTA_OFFSET=0x650000
|
||||
fi
|
||||
done
|
||||
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
|
||||
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
|
||||
for variant in "${S3_VARIANTS[@]}"; do
|
||||
if [ -n "${FILENAME##*"$variant"*}" ]; then
|
||||
MCU="esp32s3"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$MCU" != "esp32s3" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
OTAFILE=bleota.bin
|
||||
else
|
||||
|
||||
@@ -16,7 +16,7 @@ ECHO.
|
||||
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python]
|
||||
ECHO.
|
||||
ECHO Options:
|
||||
ECHO -f filename The .bin file to flash. Custom to your device type and region. (required)
|
||||
ECHO -f filename The update .bin file to flash. Custom to your device type and region. (required)
|
||||
ECHO The file must be located in this current directory.
|
||||
ECHO -p PORT Set the environment variable for ESPTOOL_PORT.
|
||||
ECHO If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
@@ -28,7 +28,7 @@ ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4-update.bin -p C
|
||||
GOTO eof
|
||||
|
||||
:version
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.0]
|
||||
ECHO %SCRIPT_NAME% [Version 2.6.1]
|
||||
ECHO Meshtastic
|
||||
GOTO eof
|
||||
|
||||
@@ -53,6 +53,7 @@ IF "__!FILENAME!__"=="____" (
|
||||
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
|
||||
GOTO help
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!"
|
||||
IF NOT "__!FILENAME: =!__"=="__!FILENAME!__" (
|
||||
CALL :LOG_MESSAGE ERROR "Filename containing spaces are not supported."
|
||||
GOTO help
|
||||
@@ -62,7 +63,6 @@ IF "__!FILENAME!__"=="____" (
|
||||
SET "FILENAME=!FILENAME:./=!"
|
||||
)
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Filename: !FILENAME!"
|
||||
CALL :LOG_MESSAGE DEBUG "Checking if !FILENAME! exists..."
|
||||
IF NOT EXIST !FILENAME! (
|
||||
CALL :LOG_MESSAGE ERROR "File does not exist: !FILENAME!. Terminating."
|
||||
@@ -71,7 +71,7 @@ IF NOT EXIST !FILENAME! (
|
||||
|
||||
IF "!FILENAME:update=!"=="!FILENAME!" (
|
||||
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!"
|
||||
CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash update !FILENAME!."
|
||||
CALL :LOG_MESSAGE INFO "Use script device-install.bat to flash !FILENAME!."
|
||||
GOTO eof
|
||||
) ELSE (
|
||||
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!"
|
||||
@@ -95,7 +95,7 @@ IF NOT "__%PYTHON%__"=="____" (
|
||||
|
||||
CALL :LOG_MESSAGE DEBUG "Checking esptool command !ESPTOOL_CMD!..."
|
||||
!ESPTOOL_CMD! >nul 2>&1
|
||||
IF %ERRORLEVEL% GTR 2 (
|
||||
IF %ERRORLEVEL% GEQ 2 (
|
||||
@REM esptool exits with code 1 if help is displayed.
|
||||
CALL :LOG_MESSAGE ERROR "esptool not found: !ESPTOOL_CMD!"
|
||||
EXIT /B 1
|
||||
@@ -110,6 +110,7 @@ CALL :LOG_MESSAGE DEBUG "Using esptool command: !ESPTOOL_CMD!"
|
||||
IF "__!ESPTOOL_PORT!__" == "____" (
|
||||
CALL :LOG_MESSAGE WARN "Using esptool port: UNSET."
|
||||
) ELSE (
|
||||
SET "ESPTOOL_CMD=!ESPTOOL_CMD! --port !ESPTOOL_PORT!"
|
||||
CALL :LOG_MESSAGE INFO "Using esptool port: !ESPTOOL_PORT!."
|
||||
)
|
||||
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
|
||||
|
||||
@@ -35,8 +35,8 @@ while getopts ":hp:P:f:" opt; do
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
p) export ESPTOOL_PORT=${OPTARG}
|
||||
;;
|
||||
p) ESPTOOL_CMD="$ESPTOOL_CMD --port ${OPTARG}"
|
||||
;;
|
||||
P) PYTHON=${OPTARG}
|
||||
;;
|
||||
f) FILENAME=${OPTARG}
|
||||
|
||||
@@ -83,7 +83,7 @@ if platform.name == "espressif32":
|
||||
|
||||
if platform.name == "nordicnrf52":
|
||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex",
|
||||
env.VerboseAction(f"{sys.executable} ./bin/uf2conv.py $BUILD_DIR/firmware.hex -c -f 0xADA52840 -o $BUILD_DIR/firmware.uf2",
|
||||
env.VerboseAction(f"\"{sys.executable}\" ./bin/uf2conv.py $BUILD_DIR/firmware.hex -c -f 0xADA52840 -o $BUILD_DIR/firmware.uf2",
|
||||
"Generating UF2 file"))
|
||||
|
||||
Import("projenv")
|
||||
|
||||
22
extra_scripts/extra_stm32.py
Executable file
22
extra_scripts/extra_stm32.py
Executable file
@@ -0,0 +1,22 @@
|
||||
# trunk-ignore-all(ruff/F821)
|
||||
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||
|
||||
Import("env")
|
||||
# Custom HEX from ELF
|
||||
env.AddPostAction(
|
||||
"$BUILD_DIR/${PROGNAME}.elf",
|
||||
env.VerboseAction(
|
||||
" ".join(
|
||||
[
|
||||
"$OBJCOPY",
|
||||
"-O",
|
||||
"ihex",
|
||||
"-R",
|
||||
".eeprom",
|
||||
"$BUILD_DIR/${PROGNAME}.elf",
|
||||
"$BUILD_DIR/${PROGNAME}.hex",
|
||||
]
|
||||
),
|
||||
"Building $BUILD_DIR/${PROGNAME}.hex",
|
||||
),
|
||||
)
|
||||
@@ -94,7 +94,7 @@ lib_deps =
|
||||
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/device-ui.git#74e739ed4532ca10393df9fc89ae5a22f0bab2b1
|
||||
https://github.com/meshtastic/device-ui.git#7a6ffba3c86901b0e3234b6c056aa803b4cd8854
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
|
||||
Submodule protobufs updated: 14ec205865...b4044f8f9f
@@ -41,10 +41,8 @@ class AudioThread : public concurrency::OSThread
|
||||
delete i2sRtttl;
|
||||
i2sRtttl = nullptr;
|
||||
}
|
||||
if (rtttlFile != nullptr) {
|
||||
delete rtttlFile;
|
||||
rtttlFile = nullptr;
|
||||
}
|
||||
delete rtttlFile;
|
||||
rtttlFile = nullptr;
|
||||
|
||||
setCPUFast(false);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
||||
#ifdef USERPREFS_BUTTON_PIN
|
||||
int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
|
||||
#endif
|
||||
#if defined(HELTEC_CAPSULE_SENSOR_V3)
|
||||
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
|
||||
this->userButton = OneButton(pin, false, false);
|
||||
#elif defined(BUTTON_ACTIVE_LOW)
|
||||
this->userButton = OneButton(pin, BUTTON_ACTIVE_LOW, BUTTON_ACTIVE_PULLUP);
|
||||
|
||||
@@ -29,30 +29,6 @@ SPIClass SPI1(HSPI);
|
||||
|
||||
#endif // HAS_SDCARD
|
||||
|
||||
#if defined(ARCH_STM32WL)
|
||||
|
||||
uint16_t OSFS::startOfEEPROM = 1;
|
||||
uint16_t OSFS::endOfEEPROM = 2048;
|
||||
|
||||
// 3) How do I read from the medium?
|
||||
void OSFS::readNBytes(uint16_t address, unsigned int num, byte *output)
|
||||
{
|
||||
for (uint16_t i = address; i < address + num; i++) {
|
||||
*output = EEPROM.read(i);
|
||||
output++;
|
||||
}
|
||||
}
|
||||
|
||||
// 4) How to I write to the medium?
|
||||
void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
|
||||
{
|
||||
for (uint16_t i = address; i < address + num; i++) {
|
||||
EEPROM.update(i, *input);
|
||||
input++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Copies a file from one location to another.
|
||||
*
|
||||
@@ -62,33 +38,7 @@ void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
|
||||
*/
|
||||
bool copyFile(const char *from, const char *to)
|
||||
{
|
||||
#ifdef ARCH_STM32WL
|
||||
unsigned char cbuffer[2048];
|
||||
|
||||
// Var to hold the result of actions
|
||||
OSFS::result r;
|
||||
|
||||
r = OSFS::getFile(from, cbuffer);
|
||||
|
||||
if (r == notfound) {
|
||||
LOG_ERROR("Failed to open source file %s", from);
|
||||
return false;
|
||||
} else if (r == noerr) {
|
||||
r = OSFS::newFile(to, cbuffer, true);
|
||||
if (r == noerr) {
|
||||
return true;
|
||||
} else {
|
||||
LOG_ERROR("OSFS Error %d", r);
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG_ERROR("OSFS Error %d", r);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
#elif defined(FSCom)
|
||||
#ifdef FSCom
|
||||
// take SPI Lock
|
||||
concurrency::LockGuard g(spiLock);
|
||||
unsigned char cbuffer[16];
|
||||
@@ -127,13 +77,7 @@ bool copyFile(const char *from, const char *to)
|
||||
*/
|
||||
bool renameFile(const char *pathFrom, const char *pathTo)
|
||||
{
|
||||
#ifdef ARCH_STM32WL
|
||||
if (copyFile(pathFrom, pathTo) && (OSFS::deleteFile(pathFrom) == OSFS::result::NO_ERROR)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#elif defined(FSCom)
|
||||
#ifdef FSCom
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// take SPI Lock
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_STM32WL)
|
||||
// STM32WL series 2 Kbytes (8 rows of 256 bytes)
|
||||
#include <EEPROM.h>
|
||||
#include <OSFS.h>
|
||||
|
||||
// Useful consts
|
||||
const OSFS::result noerr = OSFS::result::NO_ERROR;
|
||||
const OSFS::result notfound = OSFS::result::FILE_NOT_FOUND;
|
||||
// STM32WL
|
||||
#include "LittleFS.h"
|
||||
#define FSCom InternalFS
|
||||
#define FSBegin() FSCom.begin()
|
||||
using namespace STM32_LittleFS_Namespace;
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_RP2040)
|
||||
|
||||
@@ -391,7 +391,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
virtual bool isVbusIn() override
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
#ifdef HELTEC_CAPSULE_SENSOR_V3
|
||||
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
|
||||
// if external powered that pin will be pulled down
|
||||
if (digitalRead(EXT_PWR_DETECT) == LOW) {
|
||||
return true;
|
||||
@@ -541,7 +541,7 @@ Power::Power() : OSThread("Power")
|
||||
bool Power::analogInit()
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
#ifdef HELTEC_CAPSULE_SENSOR_V3
|
||||
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
|
||||
pinMode(EXT_PWR_DETECT, INPUT_PULLUP);
|
||||
#else
|
||||
pinMode(EXT_PWR_DETECT, INPUT);
|
||||
|
||||
@@ -110,6 +110,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// Define if screen should be mirrored left to right
|
||||
// #define SCREEN_MIRROR
|
||||
|
||||
// Define BUTTON_PIN to ensure button setup is always done
|
||||
#ifndef BUTTON_PIN
|
||||
#define BUTTON_PIN (-1)
|
||||
#endif
|
||||
|
||||
// I2C Keyboards (M5Stack, RAK14004, T-Deck)
|
||||
#define CARDKB_ADDR 0x5F
|
||||
#define TDECK_KB_ADDR 0x55
|
||||
@@ -152,6 +157,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MLX90614_ADDR_DEF 0x5A
|
||||
#define CGRADSENS_ADDR 0x66
|
||||
#define LTR390UV_ADDR 0x53
|
||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
@@ -369,4 +375,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endif
|
||||
|
||||
#include "DebugConfiguration.h"
|
||||
#include "RF95Configuration.h"
|
||||
#include "RF95Configuration.h"
|
||||
@@ -31,8 +31,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB};
|
||||
return firstOfOrNONE(5, types);
|
||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB, TCA8418KB};
|
||||
return firstOfOrNONE(6, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||
@@ -74,4 +74,4 @@ bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) cons
|
||||
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address));
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
|
||||
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
|
||||
|
||||
@@ -18,7 +18,7 @@ class ScanI2C
|
||||
TDECKKB,
|
||||
BBQ10KB,
|
||||
RAK14004,
|
||||
PMU_AXP192_AXP2101,
|
||||
PMU_AXP192_AXP2101, // has the same address as the TCA8418KB
|
||||
BME_680,
|
||||
BME_280,
|
||||
BMP_280,
|
||||
@@ -69,6 +69,7 @@ class ScanI2C
|
||||
DFROBOT_RAIN,
|
||||
DPS310,
|
||||
LTR390UV,
|
||||
TCA8418KB,
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
@@ -132,4 +133,4 @@ class ScanI2C
|
||||
|
||||
private:
|
||||
bool shouldSuppressScreen = false;
|
||||
};
|
||||
};
|
||||
@@ -10,11 +10,6 @@
|
||||
#include "meshUtils.h" // vformat
|
||||
#endif
|
||||
|
||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
||||
#endif
|
||||
|
||||
bool in_array(uint8_t *array, int size, uint8_t lookfor)
|
||||
{
|
||||
int i;
|
||||
@@ -211,6 +206,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
}
|
||||
break;
|
||||
|
||||
case XPOWERS_AXP192_AXP2101_ADDRESS:
|
||||
// Do we have the TCA8418 instead?
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x02), 1);
|
||||
if ((registerValue & 0b11100000) == 0) {
|
||||
logFoundDevice("TCA8418", (uint8_t)addr.address);
|
||||
type = TCA8418KB;
|
||||
} else {
|
||||
logFoundDevice("AXP192/AXP2101", (uint8_t)addr.address);
|
||||
type = PMU_AXP192_AXP2101;
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
||||
|
||||
@@ -218,9 +225,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
#ifdef HAS_NCP5623
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
|
||||
#endif
|
||||
#ifdef HAS_PMU
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address)
|
||||
#endif
|
||||
|
||||
case BME_ADDR:
|
||||
case BME_ADDR_ALTERNATE:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
|
||||
@@ -536,4 +541,4 @@ void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
|
||||
{
|
||||
LOG_INFO("%s found at address 0x%x", device, address);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1200,12 +1200,12 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
PROBE_SIMPLE("LC86", "$PQTMVERNO*58", "$PQTMVERNO,LC86", GNSS_MODEL_AG3352, 500);
|
||||
PROBE_SIMPLE("L76K", "$PCAS06,0*1B", "$GPTXT,01,01,02,SW=", GNSS_MODEL_MTK, 500);
|
||||
|
||||
// Close all NMEA sentences, valid for L76B MTK platform (Waveshare Pico GPS)
|
||||
// Close all NMEA sentences, valid for MTK3333 and MTK3339 platforms
|
||||
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
|
||||
delay(20);
|
||||
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
|
||||
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
|
||||
{"LS20031", "MC-1513", GNSS_MODEL_LS20031}};
|
||||
{"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}};
|
||||
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
|
||||
|
||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
@@ -119,7 +119,7 @@ void tftSetup(void)
|
||||
#ifdef ARCH_ESP32
|
||||
tftSleepObserver.observe(¬ifyLightSleep);
|
||||
endSleepObserver.observe(¬ifyLightSleepEnd);
|
||||
xTaskCreatePinnedToCore(tft_task_handler, "tft", 8192, NULL, 1, NULL, 0);
|
||||
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
561
src/input/TCA8418Keyboard.cpp
Normal file
561
src/input/TCA8418Keyboard.cpp
Normal file
@@ -0,0 +1,561 @@
|
||||
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
||||
|
||||
#include "TCA8418Keyboard.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// REGISTERS
|
||||
// #define _TCA8418_REG_RESERVED 0x00
|
||||
#define _TCA8418_REG_CFG 0x01 // Configuration register
|
||||
#define _TCA8418_REG_INT_STAT 0x02 // Interrupt status
|
||||
#define _TCA8418_REG_KEY_LCK_EC 0x03 // Key lock and event counter
|
||||
#define _TCA8418_REG_KEY_EVENT_A 0x04 // Key event register A
|
||||
#define _TCA8418_REG_KEY_EVENT_B 0x05 // Key event register B
|
||||
#define _TCA8418_REG_KEY_EVENT_C 0x06 // Key event register C
|
||||
#define _TCA8418_REG_KEY_EVENT_D 0x07 // Key event register D
|
||||
#define _TCA8418_REG_KEY_EVENT_E 0x08 // Key event register E
|
||||
#define _TCA8418_REG_KEY_EVENT_F 0x09 // Key event register F
|
||||
#define _TCA8418_REG_KEY_EVENT_G 0x0A // Key event register G
|
||||
#define _TCA8418_REG_KEY_EVENT_H 0x0B // Key event register H
|
||||
#define _TCA8418_REG_KEY_EVENT_I 0x0C // Key event register I
|
||||
#define _TCA8418_REG_KEY_EVENT_J 0x0D // Key event register J
|
||||
#define _TCA8418_REG_KP_LCK_TIMER 0x0E // Keypad lock1 to lock2 timer
|
||||
#define _TCA8418_REG_UNLOCK_1 0x0F // Unlock register 1
|
||||
#define _TCA8418_REG_UNLOCK_2 0x10 // Unlock register 2
|
||||
#define _TCA8418_REG_GPIO_INT_STAT_1 0x11 // GPIO interrupt status 1
|
||||
#define _TCA8418_REG_GPIO_INT_STAT_2 0x12 // GPIO interrupt status 2
|
||||
#define _TCA8418_REG_GPIO_INT_STAT_3 0x13 // GPIO interrupt status 3
|
||||
#define _TCA8418_REG_GPIO_DAT_STAT_1 0x14 // GPIO data status 1
|
||||
#define _TCA8418_REG_GPIO_DAT_STAT_2 0x15 // GPIO data status 2
|
||||
#define _TCA8418_REG_GPIO_DAT_STAT_3 0x16 // GPIO data status 3
|
||||
#define _TCA8418_REG_GPIO_DAT_OUT_1 0x17 // GPIO data out 1
|
||||
#define _TCA8418_REG_GPIO_DAT_OUT_2 0x18 // GPIO data out 2
|
||||
#define _TCA8418_REG_GPIO_DAT_OUT_3 0x19 // GPIO data out 3
|
||||
#define _TCA8418_REG_GPIO_INT_EN_1 0x1A // GPIO interrupt enable 1
|
||||
#define _TCA8418_REG_GPIO_INT_EN_2 0x1B // GPIO interrupt enable 2
|
||||
#define _TCA8418_REG_GPIO_INT_EN_3 0x1C // GPIO interrupt enable 3
|
||||
#define _TCA8418_REG_KP_GPIO_1 0x1D // Keypad/GPIO select 1
|
||||
#define _TCA8418_REG_KP_GPIO_2 0x1E // Keypad/GPIO select 2
|
||||
#define _TCA8418_REG_KP_GPIO_3 0x1F // Keypad/GPIO select 3
|
||||
#define _TCA8418_REG_GPI_EM_1 0x20 // GPI event mode 1
|
||||
#define _TCA8418_REG_GPI_EM_2 0x21 // GPI event mode 2
|
||||
#define _TCA8418_REG_GPI_EM_3 0x22 // GPI event mode 3
|
||||
#define _TCA8418_REG_GPIO_DIR_1 0x23 // GPIO data direction 1
|
||||
#define _TCA8418_REG_GPIO_DIR_2 0x24 // GPIO data direction 2
|
||||
#define _TCA8418_REG_GPIO_DIR_3 0x25 // GPIO data direction 3
|
||||
#define _TCA8418_REG_GPIO_INT_LVL_1 0x26 // GPIO edge/level detect 1
|
||||
#define _TCA8418_REG_GPIO_INT_LVL_2 0x27 // GPIO edge/level detect 2
|
||||
#define _TCA8418_REG_GPIO_INT_LVL_3 0x28 // GPIO edge/level detect 3
|
||||
#define _TCA8418_REG_DEBOUNCE_DIS_1 0x29 // Debounce disable 1
|
||||
#define _TCA8418_REG_DEBOUNCE_DIS_2 0x2A // Debounce disable 2
|
||||
#define _TCA8418_REG_DEBOUNCE_DIS_3 0x2B // Debounce disable 3
|
||||
#define _TCA8418_REG_GPIO_PULL_1 0x2C // GPIO pull-up disable 1
|
||||
#define _TCA8418_REG_GPIO_PULL_2 0x2D // GPIO pull-up disable 2
|
||||
#define _TCA8418_REG_GPIO_PULL_3 0x2E // GPIO pull-up disable 3
|
||||
// #define _TCA8418_REG_RESERVED 0x2F
|
||||
|
||||
// FIELDS CONFIG REGISTER 1
|
||||
#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write
|
||||
#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config
|
||||
#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable
|
||||
#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config
|
||||
#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable
|
||||
#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable
|
||||
#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable
|
||||
#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable
|
||||
|
||||
// FIELDS INT_STAT REGISTER 2
|
||||
#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status
|
||||
#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status
|
||||
#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status
|
||||
#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status
|
||||
#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status
|
||||
|
||||
// FIELDS KEY_LCK_EC REGISTER 3
|
||||
#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable
|
||||
#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2
|
||||
#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1
|
||||
#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3
|
||||
#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2
|
||||
#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1
|
||||
#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0
|
||||
|
||||
// Pin IDs for matrix rows/columns
|
||||
enum {
|
||||
_TCA8418_ROW0, // Pin ID for row 0
|
||||
_TCA8418_ROW1, // Pin ID for row 1
|
||||
_TCA8418_ROW2, // Pin ID for row 2
|
||||
_TCA8418_ROW3, // Pin ID for row 3
|
||||
_TCA8418_ROW4, // Pin ID for row 4
|
||||
_TCA8418_ROW5, // Pin ID for row 5
|
||||
_TCA8418_ROW6, // Pin ID for row 6
|
||||
_TCA8418_ROW7, // Pin ID for row 7
|
||||
_TCA8418_COL0, // Pin ID for column 0
|
||||
_TCA8418_COL1, // Pin ID for column 1
|
||||
_TCA8418_COL2, // Pin ID for column 2
|
||||
_TCA8418_COL3, // Pin ID for column 3
|
||||
_TCA8418_COL4, // Pin ID for column 4
|
||||
_TCA8418_COL5, // Pin ID for column 5
|
||||
_TCA8418_COL6, // Pin ID for column 6
|
||||
_TCA8418_COL7, // Pin ID for column 7
|
||||
_TCA8418_COL8, // Pin ID for column 8
|
||||
_TCA8418_COL9 // Pin ID for column 9
|
||||
};
|
||||
|
||||
#define _TCA8418_COLS 3
|
||||
#define _TCA8418_ROWS 4
|
||||
#define _TCA8418_NUM_KEYS 12
|
||||
|
||||
uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7,
|
||||
9, 7, 9, 2, 2, 2}; // Num chars per key, Modulus for rotating through characters
|
||||
|
||||
unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
|
||||
{'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, // 1
|
||||
{'2', 'a', 'b', 'c', 'A', 'B', 'C'}, // 2
|
||||
{'3', 'd', 'e', 'f', 'D', 'E', 'F'}, // 3
|
||||
{'4', 'g', 'h', 'i', 'G', 'H', 'I'}, // 4
|
||||
{'5', 'j', 'k', 'l', 'J', 'K', 'L'}, // 5
|
||||
{'6', 'm', 'n', 'o', 'M', 'N', 'O'}, // 6
|
||||
{'7', 'p', 'q', 'r', 's', 'P', 'Q', 'R', 'S'}, // 7
|
||||
{'8', 't', 'u', 'v', 'T', 'U', 'V'}, // 8
|
||||
{'9', 'w', 'x', 'y', 'z', 'W', 'X', 'Y', 'Z'}, // 9
|
||||
{'*', '+'}, // *
|
||||
{'0', ' '}, // 0
|
||||
{'#', '@'}, // #
|
||||
};
|
||||
|
||||
unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
|
||||
_TCA8418_ESC, // 1
|
||||
_TCA8418_UP, // 2
|
||||
_TCA8418_NONE, // 3
|
||||
_TCA8418_LEFT, // 4
|
||||
_TCA8418_NONE, // 5
|
||||
_TCA8418_RIGHT, // 6
|
||||
_TCA8418_NONE, // 7
|
||||
_TCA8418_DOWN, // 8
|
||||
_TCA8418_NONE, // 9
|
||||
_TCA8418_BSP, // *
|
||||
_TCA8418_NONE, // 0
|
||||
_TCA8418_NONE, // #
|
||||
};
|
||||
|
||||
#define _TCA8418_LONG_PRESS_THRESHOLD 2000
|
||||
#define _TCA8418_MULTI_TAP_THRESHOLD 750
|
||||
|
||||
TCA8418Keyboard::TCA8418Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
|
||||
{
|
||||
state = Init;
|
||||
last_key = -1;
|
||||
next_key = -1;
|
||||
should_backspace = false;
|
||||
last_tap = 0L;
|
||||
char_idx = 0;
|
||||
tap_interval = 0;
|
||||
backlight_on = true;
|
||||
queue = "";
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::begin(uint8_t addr, TwoWire *wire)
|
||||
{
|
||||
m_addr = addr;
|
||||
m_wire = wire;
|
||||
|
||||
m_wire->begin();
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
||||
{
|
||||
m_addr = addr;
|
||||
m_wire = nullptr;
|
||||
writeCallback = w;
|
||||
readCallback = r;
|
||||
reset();
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::reset()
|
||||
{
|
||||
LOG_DEBUG("TCA8418 Reset");
|
||||
// GPIO
|
||||
// set default all GIO pins to INPUT
|
||||
writeRegister(_TCA8418_REG_GPIO_DIR_1, 0x00);
|
||||
writeRegister(_TCA8418_REG_GPIO_DIR_2, 0x00);
|
||||
// Set COL9 as GPIO output
|
||||
writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x02);
|
||||
// Switch off keyboard backlight (COL9 = LOW)
|
||||
writeRegister(_TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
|
||||
|
||||
// add all pins to key events
|
||||
writeRegister(_TCA8418_REG_GPI_EM_1, 0xFF);
|
||||
writeRegister(_TCA8418_REG_GPI_EM_2, 0xFF);
|
||||
writeRegister(_TCA8418_REG_GPI_EM_3, 0xFF);
|
||||
|
||||
// set all pins to FALLING interrupts
|
||||
writeRegister(_TCA8418_REG_GPIO_INT_LVL_1, 0x00);
|
||||
writeRegister(_TCA8418_REG_GPIO_INT_LVL_2, 0x00);
|
||||
writeRegister(_TCA8418_REG_GPIO_INT_LVL_3, 0x00);
|
||||
|
||||
// add all pins to interrupts
|
||||
writeRegister(_TCA8418_REG_GPIO_INT_EN_1, 0xFF);
|
||||
writeRegister(_TCA8418_REG_GPIO_INT_EN_2, 0xFF);
|
||||
writeRegister(_TCA8418_REG_GPIO_INT_EN_3, 0xFF);
|
||||
|
||||
// Set keyboard matrix size
|
||||
matrix(_TCA8418_ROWS, _TCA8418_COLS);
|
||||
enableDebounce();
|
||||
flush();
|
||||
state = Idle;
|
||||
}
|
||||
|
||||
bool TCA8418Keyboard::matrix(uint8_t rows, uint8_t columns)
|
||||
{
|
||||
if ((rows > 8) || (columns > 10))
|
||||
return false;
|
||||
|
||||
// Skip zero size matrix
|
||||
if ((rows != 0) && (columns != 0)) {
|
||||
// Setup the keypad matrix.
|
||||
uint8_t mask = 0x00;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
mask <<= 1;
|
||||
mask |= 1;
|
||||
}
|
||||
writeRegister(_TCA8418_REG_KP_GPIO_1, mask);
|
||||
|
||||
mask = 0x00;
|
||||
for (int c = 0; c < columns && c < 8; c++) {
|
||||
mask <<= 1;
|
||||
mask |= 1;
|
||||
}
|
||||
writeRegister(_TCA8418_REG_KP_GPIO_2, mask);
|
||||
|
||||
if (columns > 8) {
|
||||
if (columns == 9)
|
||||
mask = 0x01;
|
||||
else
|
||||
mask = 0x03;
|
||||
writeRegister(_TCA8418_REG_KP_GPIO_3, mask);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t TCA8418Keyboard::keyCount() const
|
||||
{
|
||||
uint8_t eventCount = readRegister(_TCA8418_REG_KEY_LCK_EC);
|
||||
eventCount &= 0x0F; // lower 4 bits only
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
bool TCA8418Keyboard::hasEvent()
|
||||
{
|
||||
return queue.length() > 0;
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::queueEvent(char next)
|
||||
{
|
||||
if (next == _TCA8418_NONE) {
|
||||
return;
|
||||
}
|
||||
queue.concat(next);
|
||||
}
|
||||
|
||||
char TCA8418Keyboard::dequeueEvent()
|
||||
{
|
||||
if (queue.length() < 1) {
|
||||
return _TCA8418_NONE;
|
||||
}
|
||||
char next = queue.charAt(0);
|
||||
queue.remove(0, 1);
|
||||
return next;
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::trigger()
|
||||
{
|
||||
if (keyCount() == 0) {
|
||||
return;
|
||||
}
|
||||
if (state != Init) {
|
||||
// Read the key register
|
||||
uint8_t k = readRegister(_TCA8418_REG_KEY_EVENT_A);
|
||||
uint8_t key = k & 0x7F;
|
||||
if (k & 0x80) {
|
||||
if (state == Idle)
|
||||
pressed(key);
|
||||
return;
|
||||
} else {
|
||||
if (state == Held) {
|
||||
released();
|
||||
}
|
||||
state = Idle;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::pressed(uint8_t key)
|
||||
{
|
||||
if (state == Init || state == Busy) {
|
||||
return;
|
||||
}
|
||||
uint8_t next_key = 0;
|
||||
int row = (key - 1) / 10;
|
||||
int col = (key - 1) % 10;
|
||||
|
||||
if (row >= _TCA8418_ROWS || col >= _TCA8418_COLS) {
|
||||
return; // Invalid key
|
||||
}
|
||||
|
||||
// Compute key index based on dynamic row/column
|
||||
next_key = row * _TCA8418_COLS + col;
|
||||
|
||||
// LOG_DEBUG("TCA8418: Key %u -> Next Key %u", key, next_key);
|
||||
|
||||
state = Held;
|
||||
uint32_t now = millis();
|
||||
tap_interval = now - last_tap;
|
||||
if (tap_interval < 0) {
|
||||
// Long running, millis has overflowed.
|
||||
last_tap = 0;
|
||||
state = Busy;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the key is the same as the last one or if the time interval has passed
|
||||
if (next_key != last_key || tap_interval > _TCA8418_MULTI_TAP_THRESHOLD) {
|
||||
char_idx = 0; // Reset char index if new key or long press
|
||||
should_backspace = false; // dont backspace on new key
|
||||
} else {
|
||||
char_idx += 1; // Cycle through characters if same key pressed
|
||||
should_backspace = true; // allow backspace on same key
|
||||
}
|
||||
|
||||
// Store the current key as the last key
|
||||
last_key = next_key;
|
||||
last_tap = now;
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::released()
|
||||
{
|
||||
if (state != Held) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (last_key < 0 || last_key > _TCA8418_NUM_KEYS) { // reset to idle if last_key out of bounds
|
||||
last_key = -1;
|
||||
state = Idle;
|
||||
return;
|
||||
}
|
||||
uint32_t now = millis();
|
||||
int32_t held_interval = now - last_tap;
|
||||
last_tap = now;
|
||||
if (tap_interval < _TCA8418_MULTI_TAP_THRESHOLD && should_backspace) {
|
||||
queueEvent(_TCA8418_BSP);
|
||||
}
|
||||
if (held_interval > _TCA8418_LONG_PRESS_THRESHOLD) {
|
||||
queueEvent(TCA8418LongPressMap[last_key]);
|
||||
// LOG_DEBUG("Long Press Key: %i Map: %i", last_key, TCA8418LongPressMap[last_key]);
|
||||
} else {
|
||||
queueEvent(TCA8418TapMap[last_key][(char_idx % TCA8418TapMod[last_key])]);
|
||||
// LOG_DEBUG("Key Press: %i Index:%i if %i Map: %c", last_key, char_idx, TCA8418TapMod[last_key],
|
||||
// TCA8418TapMap[last_key][(char_idx % TCA8418TapMod[last_key])]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TCA8418Keyboard::flush()
|
||||
{
|
||||
// Flush key events
|
||||
uint8_t count = 0;
|
||||
while (readRegister(_TCA8418_REG_KEY_EVENT_A) != 0)
|
||||
count++;
|
||||
// Flush gpio events
|
||||
readRegister(_TCA8418_REG_GPIO_INT_STAT_1);
|
||||
readRegister(_TCA8418_REG_GPIO_INT_STAT_2);
|
||||
readRegister(_TCA8418_REG_GPIO_INT_STAT_3);
|
||||
// Clear INT_STAT register
|
||||
writeRegister(_TCA8418_REG_INT_STAT, 3);
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8_t TCA8418Keyboard::digitalRead(uint8_t pinnum) const
|
||||
{
|
||||
if (pinnum > _TCA8418_COL9)
|
||||
return 0xFF;
|
||||
|
||||
uint8_t reg = _TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8;
|
||||
uint8_t mask = (1 << (pinnum % 8));
|
||||
|
||||
// Level 0 = low other = high
|
||||
uint8_t value = readRegister(reg);
|
||||
if (value & mask)
|
||||
return HIGH;
|
||||
return LOW;
|
||||
}
|
||||
|
||||
bool TCA8418Keyboard::digitalWrite(uint8_t pinnum, uint8_t level)
|
||||
{
|
||||
if (pinnum > _TCA8418_COL9)
|
||||
return false;
|
||||
|
||||
uint8_t reg = _TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8;
|
||||
uint8_t mask = (1 << (pinnum % 8));
|
||||
|
||||
// Level 0 = low other = high
|
||||
uint8_t value = readRegister(reg);
|
||||
if (level == LOW)
|
||||
value &= ~mask;
|
||||
else
|
||||
value |= mask;
|
||||
writeRegister(reg, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCA8418Keyboard::pinMode(uint8_t pinnum, uint8_t mode)
|
||||
{
|
||||
if (pinnum > _TCA8418_COL9)
|
||||
return false;
|
||||
|
||||
uint8_t idx = pinnum / 8;
|
||||
uint8_t reg = _TCA8418_REG_GPIO_DIR_1 + idx;
|
||||
uint8_t mask = (1 << (pinnum % 8));
|
||||
|
||||
// Mode 0 = input 1 = output
|
||||
uint8_t value = readRegister(reg);
|
||||
if (mode == OUTPUT)
|
||||
value |= mask;
|
||||
else
|
||||
value &= ~mask;
|
||||
writeRegister(reg, value);
|
||||
|
||||
// Pullup 0 = enabled 1 = disabled
|
||||
reg = _TCA8418_REG_GPIO_PULL_1 + idx;
|
||||
value = readRegister(reg);
|
||||
if (mode == INPUT_PULLUP)
|
||||
value &= ~mask;
|
||||
else
|
||||
value |= mask;
|
||||
writeRegister(reg, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCA8418Keyboard::pinIRQMode(uint8_t pinnum, uint8_t mode)
|
||||
{
|
||||
if (pinnum > _TCA8418_COL9)
|
||||
return false;
|
||||
if ((mode != RISING) && (mode != FALLING))
|
||||
return false;
|
||||
|
||||
// Mode 0 = falling 1 = rising
|
||||
uint8_t idx = pinnum / 8;
|
||||
uint8_t reg = _TCA8418_REG_GPIO_INT_LVL_1 + idx;
|
||||
uint8_t mask = (1 << (pinnum % 8));
|
||||
|
||||
uint8_t value = readRegister(reg);
|
||||
if (mode == RISING)
|
||||
value |= mask;
|
||||
else
|
||||
value &= ~mask;
|
||||
writeRegister(reg, value);
|
||||
|
||||
// Enable interrupt
|
||||
reg = _TCA8418_REG_GPIO_INT_EN_1 + idx;
|
||||
value = readRegister(reg);
|
||||
value |= mask;
|
||||
writeRegister(reg, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::enableInterrupts()
|
||||
{
|
||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||
value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
||||
writeRegister(_TCA8418_REG_CFG, value);
|
||||
};
|
||||
|
||||
void TCA8418Keyboard::disableInterrupts()
|
||||
{
|
||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||
value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
||||
writeRegister(_TCA8418_REG_CFG, value);
|
||||
};
|
||||
|
||||
void TCA8418Keyboard::enableMatrixOverflow()
|
||||
{
|
||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||
value |= _TCA8418_REG_CFG_OVR_FLOW_M;
|
||||
writeRegister(_TCA8418_REG_CFG, value);
|
||||
};
|
||||
|
||||
void TCA8418Keyboard::disableMatrixOverflow()
|
||||
{
|
||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||
value &= ~_TCA8418_REG_CFG_OVR_FLOW_M;
|
||||
writeRegister(_TCA8418_REG_CFG, value);
|
||||
};
|
||||
|
||||
void TCA8418Keyboard::enableDebounce()
|
||||
{
|
||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0x00);
|
||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0x00);
|
||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0x00);
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::disableDebounce()
|
||||
{
|
||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0xFF);
|
||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0xFF);
|
||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0xFF);
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::setBacklight(bool on)
|
||||
{
|
||||
if (on) {
|
||||
digitalWrite(_TCA8418_COL9, HIGH);
|
||||
} else {
|
||||
digitalWrite(_TCA8418_COL9, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TCA8418Keyboard::readRegister(uint8_t reg) const
|
||||
{
|
||||
if (m_wire) {
|
||||
m_wire->beginTransmission(m_addr);
|
||||
m_wire->write(reg);
|
||||
m_wire->endTransmission();
|
||||
|
||||
m_wire->requestFrom(m_addr, (uint8_t)1);
|
||||
if (m_wire->available() < 1)
|
||||
return 0;
|
||||
|
||||
return m_wire->read();
|
||||
}
|
||||
if (readCallback) {
|
||||
uint8_t data;
|
||||
readCallback(m_addr, reg, &data, 1);
|
||||
return data;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TCA8418Keyboard::writeRegister(uint8_t reg, uint8_t value)
|
||||
{
|
||||
uint8_t data[2];
|
||||
data[0] = reg;
|
||||
data[1] = value;
|
||||
|
||||
if (m_wire) {
|
||||
m_wire->beginTransmission(m_addr);
|
||||
m_wire->write(data, sizeof(uint8_t) * 2);
|
||||
m_wire->endTransmission();
|
||||
}
|
||||
if (writeCallback) {
|
||||
writeCallback(m_addr, data[0], &(data[1]), 1);
|
||||
}
|
||||
}
|
||||
83
src/input/TCA8418Keyboard.h
Normal file
83
src/input/TCA8418Keyboard.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
||||
#include "configuration.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define _TCA8418_NONE 0x00
|
||||
#define _TCA8418_REBOOT 0x90
|
||||
#define _TCA8418_LEFT 0xb4
|
||||
#define _TCA8418_UP 0xb5
|
||||
#define _TCA8418_DOWN 0xb6
|
||||
#define _TCA8418_RIGHT 0xb7
|
||||
#define _TCA8418_ESC 0x1b
|
||||
#define _TCA8418_BSP 0x08
|
||||
#define _TCA8418_SELECT 0x0d
|
||||
|
||||
class TCA8418Keyboard
|
||||
{
|
||||
public:
|
||||
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
|
||||
|
||||
enum KeyState { Init = 0, Idle, Held, Busy };
|
||||
|
||||
KeyState state;
|
||||
int8_t last_key;
|
||||
int8_t next_key;
|
||||
bool should_backspace;
|
||||
uint32_t last_tap;
|
||||
uint8_t char_idx;
|
||||
int32_t tap_interval;
|
||||
bool backlight_on;
|
||||
|
||||
String queue;
|
||||
|
||||
TCA8418Keyboard();
|
||||
|
||||
void begin(uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS, TwoWire *wire = &Wire);
|
||||
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS);
|
||||
|
||||
void reset(void);
|
||||
// Configure the size of the keypad.
|
||||
// All other rows and columns are set as inputs.
|
||||
bool matrix(uint8_t rows, uint8_t columns);
|
||||
|
||||
// Flush all events in the FIFO buffer + GPIO events.
|
||||
uint8_t flush(void);
|
||||
|
||||
// Key events available in the internal FIFO buffer.
|
||||
uint8_t keyCount(void) const;
|
||||
|
||||
void trigger(void);
|
||||
void pressed(uint8_t key);
|
||||
void released(void);
|
||||
bool hasEvent(void);
|
||||
char dequeueEvent(void);
|
||||
void queueEvent(char);
|
||||
|
||||
uint8_t digitalRead(uint8_t pinnum) const;
|
||||
bool digitalWrite(uint8_t pinnum, uint8_t level);
|
||||
bool pinMode(uint8_t pinnum, uint8_t mode);
|
||||
bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING
|
||||
|
||||
// enable / disable interrupts for matrix and GPI pins
|
||||
void enableInterrupts();
|
||||
void disableInterrupts();
|
||||
|
||||
// ignore key events when FIFO buffer is full or not.
|
||||
void enableMatrixOverflow();
|
||||
void disableMatrixOverflow();
|
||||
|
||||
// debounce keys.
|
||||
void enableDebounce();
|
||||
void disableDebounce();
|
||||
|
||||
void setBacklight(bool on);
|
||||
|
||||
uint8_t readRegister(uint8_t reg) const;
|
||||
void writeRegister(uint8_t reg, uint8_t value);
|
||||
|
||||
private:
|
||||
TwoWire *m_wire;
|
||||
uint8_t m_addr;
|
||||
i2c_com_fptr_t readCallback;
|
||||
i2c_com_fptr_t writeCallback;
|
||||
};
|
||||
@@ -12,8 +12,8 @@ void CardKbI2cImpl::init()
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
|
||||
if (cardkb_found.address == 0x00) {
|
||||
LOG_DEBUG("Rescan for I2C keyboard");
|
||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR};
|
||||
uint8_t i2caddr_asize = 4;
|
||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR, XPOWERS_AXP192_AXP2101_ADDRESS};
|
||||
uint8_t i2caddr_asize = 5;
|
||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
@@ -43,6 +43,10 @@ void CardKbI2cImpl::init()
|
||||
// assign an arbitrary value to distinguish from other models
|
||||
kb_model = 0x37;
|
||||
break;
|
||||
case ScanI2C::DeviceType::TCA8418KB:
|
||||
// assign an arbitrary value to distinguish from other models
|
||||
kb_model = 0x84;
|
||||
break;
|
||||
default:
|
||||
// use this as default since it's also just zero
|
||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
||||
@@ -63,4 +67,4 @@ void CardKbI2cImpl::init()
|
||||
}
|
||||
#endif
|
||||
inputBroker->registerSource(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ int32_t KbI2cBase::runOnce()
|
||||
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
|
||||
}
|
||||
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ScanI2C::WIRE:
|
||||
@@ -55,6 +58,9 @@ int32_t KbI2cBase::runOnce()
|
||||
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
|
||||
}
|
||||
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire);
|
||||
}
|
||||
break;
|
||||
case ScanI2C::NO_I2C:
|
||||
default:
|
||||
@@ -163,6 +169,70 @@ int32_t KbI2cBase::runOnce()
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x84: { // Adafruit TCA8418
|
||||
TCAKeyboard.trigger();
|
||||
InputEvent e;
|
||||
while (TCAKeyboard.hasEvent()) {
|
||||
char nextEvent = TCAKeyboard.dequeueEvent();
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = 0x00;
|
||||
e.source = this->_originName;
|
||||
switch (nextEvent) {
|
||||
case _TCA8418_NONE:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
e.kbchar = 0x00;
|
||||
break;
|
||||
case _TCA8418_REBOOT:
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = INPUT_BROKER_MSG_REBOOT;
|
||||
break;
|
||||
case _TCA8418_LEFT:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||
e.kbchar = 0x00;
|
||||
break;
|
||||
case _TCA8418_UP:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||
e.kbchar = 0x00;
|
||||
break;
|
||||
case _TCA8418_DOWN:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||
e.kbchar = 0x00;
|
||||
break;
|
||||
case _TCA8418_RIGHT:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||
e.kbchar = 0x00;
|
||||
break;
|
||||
case _TCA8418_BSP:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||
e.kbchar = 0x08;
|
||||
break;
|
||||
case _TCA8418_SELECT:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||
e.kbchar = 0x0d;
|
||||
break;
|
||||
case _TCA8418_ESC:
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||
e.kbchar = 0x1b;
|
||||
break;
|
||||
default:
|
||||
if (nextEvent > 127) {
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
e.kbchar = 0x00;
|
||||
break;
|
||||
}
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = nextEvent;
|
||||
break;
|
||||
}
|
||||
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||
LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x37: { // MPR121
|
||||
MPRkeyboard.trigger();
|
||||
InputEvent e;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "BBQ10Keyboard.h"
|
||||
#include "InputBroker.h"
|
||||
#include "MPR121Keyboard.h"
|
||||
#include "TCA8418Keyboard.h"
|
||||
#include "Wire.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
@@ -21,5 +22,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
||||
|
||||
BBQ10Keyboard Q10keyboard;
|
||||
MPR121Keyboard MPRkeyboard;
|
||||
TCA8418Keyboard TCAKeyboard;
|
||||
bool is_sym = false;
|
||||
};
|
||||
};
|
||||
|
||||
11
src/main.cpp
11
src/main.cpp
@@ -568,6 +568,10 @@ void setup()
|
||||
// assign an arbitrary value to distinguish from other models
|
||||
kb_model = 0x37;
|
||||
break;
|
||||
case ScanI2C::DeviceType::TCA8418KB:
|
||||
// assign an arbitrary value to distinguish from other models
|
||||
kb_model = 0x84;
|
||||
break;
|
||||
default:
|
||||
// use this as default since it's also just zero
|
||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
||||
@@ -823,8 +827,11 @@ void setup()
|
||||
LOG_DEBUG("Start multicast thread");
|
||||
udpThread = new UdpMulticastThread();
|
||||
#ifdef ARCH_PORTDUINO
|
||||
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call onNetworkConnected there
|
||||
udpThread->start();
|
||||
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
|
||||
// onNetworkConnected there
|
||||
if (config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpThread->start();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
service = new MeshService();
|
||||
|
||||
@@ -161,10 +161,8 @@ void CryptoEngine::hash(uint8_t *bytes, size_t numBytes)
|
||||
|
||||
void CryptoEngine::aesSetKey(const uint8_t *key_bytes, size_t key_len)
|
||||
{
|
||||
if (aes) {
|
||||
delete aes;
|
||||
aes = nullptr;
|
||||
}
|
||||
delete aes;
|
||||
aes = nullptr;
|
||||
if (key_len != 0) {
|
||||
aes = new AESSmall256();
|
||||
aes->setKey(key_bytes, key_len);
|
||||
@@ -225,10 +223,8 @@ void CryptoEngine::decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes
|
||||
// Generic implementation of AES-CTR encryption.
|
||||
void CryptoEngine::encryptAESCtr(CryptoKey _key, uint8_t *_nonce, size_t numBytes, uint8_t *bytes)
|
||||
{
|
||||
if (ctr) {
|
||||
delete ctr;
|
||||
ctr = nullptr;
|
||||
}
|
||||
delete ctr;
|
||||
ctr = nullptr;
|
||||
if (_key.length == 16)
|
||||
ctr = new CTR<AES128>();
|
||||
else
|
||||
|
||||
@@ -309,7 +309,10 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
assert(toPhoneQueue.enqueue(p, 0));
|
||||
if (toPhoneQueue.enqueue(p, 0) == false) {
|
||||
LOG_CRIT("Failed to queue a packet into toPhoneQueue!");
|
||||
abort();
|
||||
}
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
@@ -323,7 +326,10 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
|
||||
releaseMqttClientProxyMessageToPool(d);
|
||||
}
|
||||
|
||||
assert(toPhoneMqttProxyQueue.enqueue(m, 0));
|
||||
if (toPhoneMqttProxyQueue.enqueue(m, 0) == false) {
|
||||
LOG_CRIT("Failed to queue a packet into toPhoneMqttProxyQueue!");
|
||||
abort();
|
||||
}
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
@@ -337,7 +343,10 @@ void MeshService::sendClientNotification(meshtastic_ClientNotification *n)
|
||||
releaseClientNotificationToPool(d);
|
||||
}
|
||||
|
||||
assert(toPhoneClientNotificationQueue.enqueue(n, 0));
|
||||
if (toPhoneClientNotificationQueue.enqueue(n, 0) == false) {
|
||||
LOG_CRIT("Failed to queue a notification into toPhoneClientNotificationQueue!");
|
||||
abort();
|
||||
}
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
#include <utility/bonding.h>
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
||||
#include <WiFiOTA.h>
|
||||
#endif
|
||||
|
||||
NodeDB *nodeDB = nullptr;
|
||||
|
||||
// we have plenty of ram so statically alloc this tempbuf (for now)
|
||||
@@ -624,6 +628,27 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
|
||||
meshtastic_Config_PositionConfig_PositionFlags_DOP | meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW);
|
||||
|
||||
// Set default value for 'Mesh via UDP'
|
||||
#if HAS_UDP_MULTICAST
|
||||
#ifdef USERPREFS_NETWORK_ENABLED_PROTOCOLS
|
||||
config.network.enabled_protocols = USERPREFS_NETWORK_ENABLED_PROTOCOLS;
|
||||
#else
|
||||
config.network.enabled_protocols = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_NETWORK_WIFI_ENABLED
|
||||
config.network.wifi_enabled = USERPREFS_NETWORK_WIFI_ENABLED;
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_NETWORK_WIFI_SSID
|
||||
strncpy(config.network.wifi_ssid, USERPREFS_NETWORK_WIFI_SSID, sizeof(config.network.wifi_ssid));
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_NETWORK_WIFI_PSK
|
||||
strncpy(config.network.wifi_psk, USERPREFS_NETWORK_WIFI_PSK, sizeof(config.network.wifi_psk));
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_FLIP_SCREEN
|
||||
config.display.flip_screen = true;
|
||||
#endif
|
||||
@@ -635,6 +660,12 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
config.display.wake_on_tap_or_motion = true;
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
||||
if (WiFiOTA::isUpdated()) {
|
||||
WiFiOTA::recoverConfig(&config.network);
|
||||
}
|
||||
#endif
|
||||
|
||||
initConfigIntervals();
|
||||
}
|
||||
|
||||
@@ -1427,13 +1458,14 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
if (p.public_key.size > 0) {
|
||||
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
||||
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
|
||||
LOG_INFO("Public Key set for node, not updating!");
|
||||
// we copy the key into the incoming packet, to prevent overwrite
|
||||
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
||||
} else {
|
||||
LOG_INFO("Update Node Pubkey!");
|
||||
}
|
||||
}
|
||||
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
|
||||
LOG_INFO("Public Key set for node, not updating!");
|
||||
// we copy the key into the incoming packet, to prevent overwrite
|
||||
p.public_key.size = 32;
|
||||
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
||||
} else if (p.public_key.size > 0) {
|
||||
LOG_INFO("Update Node Pubkey!");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1598,6 +1630,94 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
||||
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
||||
}
|
||||
|
||||
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
||||
{
|
||||
bool success = false;
|
||||
lastBackupAttempt = millis();
|
||||
#ifdef FSCom
|
||||
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
||||
meshtastic_BackupPreferences backup = meshtastic_BackupPreferences_init_zero;
|
||||
backup.version = DEVICESTATE_CUR_VER;
|
||||
backup.timestamp = getValidTime(RTCQuality::RTCQualityDevice, false);
|
||||
backup.has_config = true;
|
||||
backup.config = config;
|
||||
backup.has_module_config = true;
|
||||
backup.module_config = moduleConfig;
|
||||
backup.has_channels = true;
|
||||
backup.channels = channelFile;
|
||||
backup.has_owner = true;
|
||||
backup.owner = owner;
|
||||
|
||||
size_t backupSize;
|
||||
pb_get_encoded_size(&backupSize, meshtastic_BackupPreferences_fields, &backup);
|
||||
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/backups");
|
||||
spiLock->unlock();
|
||||
success = saveProto(backupFileName, backupSize, &meshtastic_BackupPreferences_msg, &backup);
|
||||
|
||||
if (success) {
|
||||
LOG_INFO("Saved backup preferences");
|
||||
} else {
|
||||
LOG_ERROR("Failed to save backup preferences to file");
|
||||
}
|
||||
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||
// TODO: After more mainline SD card support
|
||||
}
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location, int restoreWhat)
|
||||
{
|
||||
bool success = false;
|
||||
#ifdef FSCom
|
||||
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
||||
spiLock->lock();
|
||||
if (!FSCom.exists(backupFileName)) {
|
||||
spiLock->unlock();
|
||||
LOG_WARN("Could not restore. No backup file found");
|
||||
return false;
|
||||
} else {
|
||||
spiLock->unlock();
|
||||
}
|
||||
meshtastic_BackupPreferences backup = meshtastic_BackupPreferences_init_zero;
|
||||
success = loadProto(backupFileName, meshtastic_BackupPreferences_size, sizeof(meshtastic_BackupPreferences),
|
||||
&meshtastic_BackupPreferences_msg, &backup);
|
||||
if (success) {
|
||||
if (restoreWhat & SEGMENT_CONFIG) {
|
||||
config = backup.config;
|
||||
LOG_DEBUG("Restored config");
|
||||
}
|
||||
if (restoreWhat & SEGMENT_MODULECONFIG) {
|
||||
moduleConfig = backup.module_config;
|
||||
LOG_DEBUG("Restored module config");
|
||||
}
|
||||
if (restoreWhat & SEGMENT_DEVICESTATE) {
|
||||
devicestate.owner = backup.owner;
|
||||
LOG_DEBUG("Restored device state");
|
||||
}
|
||||
if (restoreWhat & SEGMENT_CHANNELS) {
|
||||
channelFile = backup.channels;
|
||||
LOG_DEBUG("Restored channels");
|
||||
}
|
||||
|
||||
success = saveToDisk(restoreWhat);
|
||||
if (success) {
|
||||
LOG_INFO("Restored preferences from backup");
|
||||
} else {
|
||||
LOG_ERROR("Failed to save restored preferences to flash");
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Failed to restore preferences from backup file");
|
||||
}
|
||||
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||
// TODO: After more mainline SD card support
|
||||
}
|
||||
return success;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Record an error that should be reported via analytics
|
||||
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@ static constexpr const char *configFileName = "/prefs/config.proto";
|
||||
static constexpr const char *uiconfigFileName = "/prefs/uiconfig.proto";
|
||||
static constexpr const char *moduleConfigFileName = "/prefs/module.proto";
|
||||
static constexpr const char *channelFileName = "/prefs/channels.proto";
|
||||
static constexpr const char *backupFileName = "/backups/backup.proto";
|
||||
|
||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
|
||||
@@ -202,8 +203,13 @@ class NodeDB
|
||||
|
||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||
|
||||
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
||||
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
|
||||
private:
|
||||
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
||||
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
||||
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
|
||||
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
|
||||
p->pki_encrypted = true;
|
||||
memcpy(&p->public_key.bytes, nodeDB->getMeshNode(p->from)->user.public_key.bytes, 32);
|
||||
p->public_key.size = 32;
|
||||
memcpy(&p->decoded, &decodedtmp, sizeof(meshtastic_Data_msg));
|
||||
p->decoded = decodedtmp;
|
||||
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded
|
||||
} else {
|
||||
LOG_ERROR("PKC Decrypted, but pb_decode failed!");
|
||||
|
||||
@@ -18,8 +18,10 @@ bool STM32WLE5JCInterface::init()
|
||||
{
|
||||
RadioLibInterface::init();
|
||||
|
||||
// https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c
|
||||
// https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c
|
||||
#if (!defined(_VARIANT_RAK3172_))
|
||||
setTCXOVoltage(1.7);
|
||||
#endif
|
||||
|
||||
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||
|
||||
@@ -42,4 +44,4 @@ bool STM32WLE5JCInterface::init()
|
||||
return res == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif // ARCH_STM32WL
|
||||
#endif // ARCH_STM32WL
|
||||
|
||||
@@ -235,6 +235,8 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_THINKNODE_M2 = 90,
|
||||
/* Lilygo T-ETH-Elite */
|
||||
meshtastic_HardwareModel_T_ETH_ELITE = 91,
|
||||
/* Heltec HRI-3621 industrial probe */
|
||||
meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
@@ -18,10 +18,30 @@
|
||||
#define MAX_RX_TOPHONE 32
|
||||
#endif
|
||||
|
||||
/// max number of nodes allowed in the mesh
|
||||
/// max number of nodes allowed in the nodeDB
|
||||
#ifndef MAX_NUM_NODES
|
||||
#if defined(ARCH_STM32WL)
|
||||
#define MAX_NUM_NODES 10
|
||||
#elif defined(ARCH_NRF52)
|
||||
#define MAX_NUM_NODES 80
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#include "Esp.h"
|
||||
static inline int get_max_num_nodes()
|
||||
{
|
||||
uint32_t flash_size = ESP.getFlashChipSize() / (1024 * 1024); // Convert Bytes to MB
|
||||
if (flash_size >= 15) {
|
||||
return 250;
|
||||
} else if (flash_size >= 7) {
|
||||
return 200;
|
||||
} else {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
#define MAX_NUM_NODES get_max_num_nodes()
|
||||
#else
|
||||
#define MAX_NUM_NODES 100
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Max number of channels allowed
|
||||
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
|
||||
|
||||
@@ -22,13 +22,13 @@ class UdpMulticastThread : public concurrency::OSThread
|
||||
|
||||
void start()
|
||||
{
|
||||
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT)) {
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
|
||||
#else
|
||||
LOG_DEBUG("UDP Listening");
|
||||
#endif
|
||||
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
|
||||
#else
|
||||
LOG_DEBUG("UDP Listening");
|
||||
#endif
|
||||
udp.onPacket([this](AsyncUDPPacket packet) { onReceive(packet); });
|
||||
} else {
|
||||
LOG_DEBUG("Failed to listen on UDP");
|
||||
@@ -38,10 +38,10 @@ class UdpMulticastThread : public concurrency::OSThread
|
||||
void onReceive(AsyncUDPPacket packet)
|
||||
{
|
||||
size_t packetLength = packet.length();
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
|
||||
#endif
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
|
||||
#endif
|
||||
meshtastic_MeshPacket mp;
|
||||
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
|
||||
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
|
||||
@@ -59,11 +59,11 @@ class UdpMulticastThread : public concurrency::OSThread
|
||||
if (!mp || !udp) {
|
||||
return false;
|
||||
}
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
#ifndef ARCH_PORTDUINO
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
LOG_DEBUG("Broadcasting packet over UDP (id=%u)", mp->id);
|
||||
uint8_t buffer[meshtastic_MeshPacket_size];
|
||||
size_t encodedLength = pb_encode_to_bytes(buffer, sizeof(buffer), &meshtastic_MeshPacket_msg, mp);
|
||||
@@ -83,4 +83,4 @@ class UdpMulticastThread : public concurrency::OSThread
|
||||
IPAddress udpIpAddress;
|
||||
AsyncUDP udp;
|
||||
};
|
||||
#endif // ARCH_ESP32
|
||||
#endif // HAS_UDP_MULTICAST
|
||||
@@ -133,7 +133,7 @@ static void onNetworkConnected()
|
||||
}
|
||||
|
||||
#if HAS_UDP_MULTICAST
|
||||
if (udpThread) {
|
||||
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpThread->start();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#include "BleOta.h"
|
||||
#endif
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
||||
#include "WiFiOTA.h"
|
||||
#endif
|
||||
#include "Router.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
@@ -194,19 +197,23 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
}
|
||||
case meshtastic_AdminMessage_reboot_ota_seconds_tag: {
|
||||
int32_t s = r->reboot_ota_seconds;
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
if (BleOta::getOtaAppVersion().isEmpty()) {
|
||||
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds", s);
|
||||
screen->startAlert("Rebooting...");
|
||||
} else {
|
||||
#if defined(ARCH_ESP32)
|
||||
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
if (!BleOta::getOtaAppVersion().isEmpty()) {
|
||||
screen->startFirmwareUpdateScreen();
|
||||
BleOta::switchToOtaApp();
|
||||
LOG_INFO("Reboot to OTA in %d seconds", s);
|
||||
LOG_INFO("Rebooting to BLE OTA");
|
||||
}
|
||||
#else
|
||||
LOG_INFO("Not on ESP32, scheduling regular reboot in %d seconds", s);
|
||||
screen->startAlert("Rebooting...");
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_WIFI
|
||||
if (WiFiOTA::trySwitchToOTA()) {
|
||||
screen->startFirmwareUpdateScreen();
|
||||
WiFiOTA::saveConfig(&config.network);
|
||||
LOG_INFO("Rebooting to WiFi OTA");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
LOG_INFO("Reboot in %d seconds", s);
|
||||
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
|
||||
break;
|
||||
}
|
||||
@@ -370,6 +377,42 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
LOG_DEBUG("Failed to delete file");
|
||||
}
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_backup_preferences_tag: {
|
||||
LOG_INFO("Client requesting to backup preferences");
|
||||
if (nodeDB->backupPreferences(r->backup_preferences)) {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
} else {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_restore_preferences_tag: {
|
||||
LOG_INFO("Client requesting to restore preferences");
|
||||
if (nodeDB->restorePreferences(r->backup_preferences,
|
||||
SEGMENT_DEVICESTATE | SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_CHANNELS)) {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
LOG_DEBUG("Rebooting after successful restore of preferences");
|
||||
reboot(1000);
|
||||
disableBluetooth();
|
||||
} else {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_remove_backup_preferences_tag: {
|
||||
LOG_INFO("Client requesting to remove backup preferences");
|
||||
#ifdef FSCom
|
||||
if (r->remove_backup_preferences == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
||||
spiLock->lock();
|
||||
FSCom.remove(backupFileName);
|
||||
spiLock->unlock();
|
||||
} else if (r->remove_backup_preferences == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||
// TODO: After more mainline SD card support
|
||||
LOG_ERROR("SD backup removal not implemented yet");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include "input/SerialKeyboardImpl.h"
|
||||
#include "input/TrackballInterruptImpl1.h"
|
||||
#include "input/UpDownInterruptImpl1.h"
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "input/cardKbI2cImpl.h"
|
||||
#endif
|
||||
#include "input/kbMatrixImpl.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_ADMIN
|
||||
|
||||
@@ -31,7 +31,7 @@ uint32_t packetSequence = 0;
|
||||
|
||||
int32_t RangeTestModule::runOnce()
|
||||
{
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
|
||||
|
||||
/*
|
||||
Uncomment the preferences below if you want to use the module
|
||||
@@ -130,7 +130,7 @@ void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
||||
|
||||
ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
|
||||
|
||||
if (moduleConfig.range_test.enabled) {
|
||||
|
||||
|
||||
@@ -468,81 +468,83 @@ void SerialModule::processWXSerial()
|
||||
// Extract the current line
|
||||
char line[meshtastic_Constants_DATA_PAYLOAD_LEN];
|
||||
memset(line, '\0', sizeof(line));
|
||||
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
|
||||
if (strstr(line, "Wind") != NULL) // we have a wind line
|
||||
{
|
||||
gotwind = true;
|
||||
// Find the positions of "=" signs in the line
|
||||
char *windDirPos = strstr(line, "WindDir = ");
|
||||
char *windSpeedPos = strstr(line, "WindSpeed = ");
|
||||
char *windGustPos = strstr(line, "WindGust = ");
|
||||
if (lineEnd - lineStart < sizeof(line) - 1) {
|
||||
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
|
||||
if (strstr(line, "Wind") != NULL) // we have a wind line
|
||||
{
|
||||
gotwind = true;
|
||||
// Find the positions of "=" signs in the line
|
||||
char *windDirPos = strstr(line, "WindDir = ");
|
||||
char *windSpeedPos = strstr(line, "WindSpeed = ");
|
||||
char *windGustPos = strstr(line, "WindGust = ");
|
||||
|
||||
if (windDirPos != NULL) {
|
||||
// Extract data after "=" for WindDir
|
||||
strcpy(windDir, windDirPos + 15); // Add 15 to skip "WindDir = "
|
||||
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
|
||||
dir_sum_sin += sin(radians);
|
||||
dir_sum_cos += cos(radians);
|
||||
dirCount++;
|
||||
} else if (windSpeedPos != NULL) {
|
||||
// Extract data after "=" for WindSpeed
|
||||
strcpy(windVel, windSpeedPos + 15); // Add 15 to skip "WindSpeed = "
|
||||
float newv = strtof(windVel, nullptr);
|
||||
velSum += newv;
|
||||
velCount++;
|
||||
if (newv < lull || lull == -1)
|
||||
lull = newv;
|
||||
if (windDirPos != NULL) {
|
||||
// Extract data after "=" for WindDir
|
||||
strlcpy(windDir, windDirPos + 15, sizeof(windDir)); // Add 15 to skip "WindDir = "
|
||||
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
|
||||
dir_sum_sin += sin(radians);
|
||||
dir_sum_cos += cos(radians);
|
||||
dirCount++;
|
||||
} else if (windSpeedPos != NULL) {
|
||||
// Extract data after "=" for WindSpeed
|
||||
strlcpy(windVel, windSpeedPos + 15, sizeof(windVel)); // Add 15 to skip "WindSpeed = "
|
||||
float newv = strtof(windVel, nullptr);
|
||||
velSum += newv;
|
||||
velCount++;
|
||||
if (newv < lull || lull == -1)
|
||||
lull = newv;
|
||||
|
||||
} else if (windGustPos != NULL) {
|
||||
strcpy(windGust, windGustPos + 15); // Add 15 to skip "WindSpeed = "
|
||||
float newg = strtof(windGust, nullptr);
|
||||
if (newg > gust)
|
||||
gust = newg;
|
||||
}
|
||||
} else if (windGustPos != NULL) {
|
||||
strlcpy(windGust, windGustPos + 15, sizeof(windGust)); // Add 15 to skip "WindSpeed = "
|
||||
float newg = strtof(windGust, nullptr);
|
||||
if (newg > gust)
|
||||
gust = newg;
|
||||
}
|
||||
|
||||
// these are also voltage data we care about possibly
|
||||
} else if (strstr(line, "BatVoltage") != NULL) { // we have a battVoltage line
|
||||
char *batVoltagePos = strstr(line, "BatVoltage = ");
|
||||
if (batVoltagePos != NULL) {
|
||||
strcpy(batVoltage, batVoltagePos + 17); // 18 for ws 80, 17 for ws85
|
||||
batVoltageF = strtof(batVoltage, nullptr);
|
||||
break; // last possible data we want so break
|
||||
}
|
||||
} else if (strstr(line, "CapVoltage") != NULL) { // we have a cappVoltage line
|
||||
char *capVoltagePos = strstr(line, "CapVoltage = ");
|
||||
if (capVoltagePos != NULL) {
|
||||
strcpy(capVoltage, capVoltagePos + 17); // 18 for ws 80, 17 for ws85
|
||||
capVoltageF = strtof(capVoltage, nullptr);
|
||||
}
|
||||
// GXTS04Temp = 24.4
|
||||
} else if (strstr(line, "GXTS04Temp") != NULL) { // we have a temperature line
|
||||
char *tempPos = strstr(line, "GXTS04Temp = ");
|
||||
if (tempPos != NULL) {
|
||||
strcpy(temperature, tempPos + 15); // 15 spaces for ws85
|
||||
temperatureF = strtof(temperature, nullptr);
|
||||
}
|
||||
// these are also voltage data we care about possibly
|
||||
} else if (strstr(line, "BatVoltage") != NULL) { // we have a battVoltage line
|
||||
char *batVoltagePos = strstr(line, "BatVoltage = ");
|
||||
if (batVoltagePos != NULL) {
|
||||
strlcpy(batVoltage, batVoltagePos + 17, sizeof(batVoltage)); // 18 for ws 80, 17 for ws85
|
||||
batVoltageF = strtof(batVoltage, nullptr);
|
||||
break; // last possible data we want so break
|
||||
}
|
||||
} else if (strstr(line, "CapVoltage") != NULL) { // we have a cappVoltage line
|
||||
char *capVoltagePos = strstr(line, "CapVoltage = ");
|
||||
if (capVoltagePos != NULL) {
|
||||
strlcpy(capVoltage, capVoltagePos + 17, sizeof(capVoltage)); // 18 for ws 80, 17 for ws85
|
||||
capVoltageF = strtof(capVoltage, nullptr);
|
||||
}
|
||||
// GXTS04Temp = 24.4
|
||||
} else if (strstr(line, "GXTS04Temp") != NULL) { // we have a temperature line
|
||||
char *tempPos = strstr(line, "GXTS04Temp = ");
|
||||
if (tempPos != NULL) {
|
||||
strlcpy(temperature, tempPos + 15, sizeof(temperature)); // 15 spaces for ws85
|
||||
temperatureF = strtof(temperature, nullptr);
|
||||
}
|
||||
|
||||
} else if (strstr(line, "RainIntSum") != NULL) { // we have a rainsum line
|
||||
// LOG_INFO(line);
|
||||
char *pos = strstr(line, "RainIntSum = ");
|
||||
if (pos != NULL) {
|
||||
strcpy(rainStr, pos + 17); // 17 spaces for ws85
|
||||
rainSum = int(strtof(rainStr, nullptr));
|
||||
}
|
||||
|
||||
} else if (strstr(line, "Rain") != NULL) { // we have a rain line
|
||||
if (strstr(line, "WaveRain") == NULL) { // skip WaveRain lines though.
|
||||
} else if (strstr(line, "RainIntSum") != NULL) { // we have a rainsum line
|
||||
// LOG_INFO(line);
|
||||
char *pos = strstr(line, "Rain = ");
|
||||
char *pos = strstr(line, "RainIntSum = ");
|
||||
if (pos != NULL) {
|
||||
strcpy(rainStr, pos + 17); // 17 spaces for ws85
|
||||
rain = strtof(rainStr, nullptr);
|
||||
strlcpy(rainStr, pos + 17, sizeof(rainStr)); // 17 spaces for ws85
|
||||
rainSum = int(strtof(rainStr, nullptr));
|
||||
}
|
||||
|
||||
} else if (strstr(line, "Rain") != NULL) { // we have a rain line
|
||||
if (strstr(line, "WaveRain") == NULL) { // skip WaveRain lines though.
|
||||
// LOG_INFO(line);
|
||||
char *pos = strstr(line, "Rain = ");
|
||||
if (pos != NULL) {
|
||||
strlcpy(rainStr, pos + 17, sizeof(rainStr)); // 17 spaces for ws85
|
||||
rain = strtof(rainStr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update lineStart for the next line
|
||||
lineStart = lineEnd + 1;
|
||||
// Update lineStart for the next line
|
||||
lineStart = lineEnd + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -98,7 +98,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
// moduleConfig.telemetry.environment_screen_enabled = 1;
|
||||
// moduleConfig.telemetry.environment_update_interval = 15;
|
||||
|
||||
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
|
||||
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled ||
|
||||
ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE)) {
|
||||
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
|
||||
return disable();
|
||||
}
|
||||
@@ -107,7 +108,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
// This is the first time the OSThread library has called this function, so do some setup
|
||||
firstTime = 0;
|
||||
|
||||
if (moduleConfig.telemetry.environment_measurement_enabled) {
|
||||
if (moduleConfig.telemetry.environment_measurement_enabled || ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
|
||||
LOG_INFO("Environment Telemetry: init");
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
result = indicatorSensor.runOnce();
|
||||
@@ -178,7 +179,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
return result == UINT32_MAX ? disable() : setStartDelay();
|
||||
} else {
|
||||
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
|
||||
if (!moduleConfig.telemetry.environment_measurement_enabled) {
|
||||
if (!moduleConfig.telemetry.environment_measurement_enabled && !ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
|
||||
return disable();
|
||||
} else {
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE
|
||||
#define ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE 0
|
||||
#endif
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "NodeDB.h"
|
||||
#include "ProtobufModule.h"
|
||||
|
||||
@@ -160,13 +160,11 @@ class AccelerometerThread : public concurrency::OSThread
|
||||
void clean()
|
||||
{
|
||||
isInitialised = false;
|
||||
if (sensor != nullptr) {
|
||||
delete sensor;
|
||||
sensor = nullptr;
|
||||
}
|
||||
delete sensor;
|
||||
sensor = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
92
src/platform/esp32/WiFiOTA.cpp
Normal file
92
src/platform/esp32/WiFiOTA.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "WiFiOTA.h"
|
||||
#include "configuration.h"
|
||||
#include <Preferences.h>
|
||||
#include <esp_ota_ops.h>
|
||||
|
||||
namespace WiFiOTA
|
||||
{
|
||||
|
||||
static const char *nvsNamespace = "ota-wifi";
|
||||
static const char *appProjectName = "OTA-WiFi";
|
||||
|
||||
static bool updated = false;
|
||||
|
||||
bool isUpdated()
|
||||
{
|
||||
return updated;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
Preferences prefs;
|
||||
prefs.begin(nvsNamespace);
|
||||
if (prefs.getBool("updated")) {
|
||||
LOG_INFO("First boot after OTA update");
|
||||
updated = true;
|
||||
prefs.putBool("updated", false);
|
||||
}
|
||||
prefs.end();
|
||||
}
|
||||
|
||||
void recoverConfig(meshtastic_Config_NetworkConfig *network)
|
||||
{
|
||||
LOG_INFO("Recovering WiFi settings after OTA update");
|
||||
|
||||
Preferences prefs;
|
||||
prefs.begin(nvsNamespace, true);
|
||||
String ssid = prefs.getString("ssid");
|
||||
String psk = prefs.getString("psk");
|
||||
prefs.end();
|
||||
|
||||
network->wifi_enabled = true;
|
||||
strncpy(network->wifi_ssid, ssid.c_str(), sizeof(network->wifi_ssid));
|
||||
strncpy(network->wifi_psk, psk.c_str(), sizeof(network->wifi_psk));
|
||||
}
|
||||
|
||||
void saveConfig(meshtastic_Config_NetworkConfig *network)
|
||||
{
|
||||
LOG_INFO("Saving WiFi settings for upcoming OTA update");
|
||||
|
||||
Preferences prefs;
|
||||
prefs.begin(nvsNamespace);
|
||||
prefs.putString("ssid", network->wifi_ssid);
|
||||
prefs.putString("psk", network->wifi_psk);
|
||||
prefs.putBool("updated", false);
|
||||
prefs.end();
|
||||
}
|
||||
|
||||
const esp_partition_t *getAppPartition()
|
||||
{
|
||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
|
||||
}
|
||||
|
||||
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
|
||||
{
|
||||
if (esp_ota_get_partition_description(part, app_desc) != ESP_OK)
|
||||
return false;
|
||||
if (strcmp(app_desc->project_name, appProjectName) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool trySwitchToOTA()
|
||||
{
|
||||
const esp_partition_t *part = getAppPartition();
|
||||
esp_app_desc_t app_desc;
|
||||
if (!getAppDesc(part, &app_desc))
|
||||
return false;
|
||||
if (esp_ota_set_boot_partition(part) != ESP_OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
String getVersion()
|
||||
{
|
||||
const esp_partition_t *part = getAppPartition();
|
||||
esp_app_desc_t app_desc;
|
||||
if (!getAppDesc(part, &app_desc))
|
||||
return String();
|
||||
return String(app_desc.version);
|
||||
}
|
||||
|
||||
} // namespace WiFiOTA
|
||||
18
src/platform/esp32/WiFiOTA.h
Normal file
18
src/platform/esp32/WiFiOTA.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef WIFIOTA_H
|
||||
#define WIFIOTA_H
|
||||
|
||||
#include "mesh-pb-constants.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace WiFiOTA
|
||||
{
|
||||
void initialize();
|
||||
bool isUpdated();
|
||||
|
||||
void recoverConfig(meshtastic_Config_NetworkConfig *network);
|
||||
void saveConfig(meshtastic_Config_NetworkConfig *network);
|
||||
bool trySwitchToOTA();
|
||||
String getVersion();
|
||||
} // namespace WiFiOTA
|
||||
|
||||
#endif // WIFIOTA_H
|
||||
@@ -178,6 +178,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_MESH_TAB
|
||||
#elif defined(T_ETH_ELITE)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_T_ETH_ELITE
|
||||
#elif defined(HELTEC_SENSOR_HUB)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_SENSOR_HUB
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
#include <WiFiOTA.h>
|
||||
|
||||
#if HAS_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
@@ -139,12 +141,19 @@ void esp32Setup()
|
||||
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
String BLEOTA = BleOta::getOtaAppVersion();
|
||||
if (BLEOTA.isEmpty()) {
|
||||
LOG_INFO("No OTA firmware available");
|
||||
LOG_INFO("No BLE OTA firmware available");
|
||||
} else {
|
||||
LOG_INFO("OTA firmware version %s", BLEOTA.c_str());
|
||||
LOG_INFO("BLE OTA firmware version %s", BLEOTA.c_str());
|
||||
}
|
||||
#else
|
||||
LOG_INFO("No OTA firmware available");
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_WIFI
|
||||
String version = WiFiOTA::getVersion();
|
||||
if (version.isEmpty()) {
|
||||
LOG_INFO("No WiFi OTA firmware available");
|
||||
} else {
|
||||
LOG_INFO("WiFi OTA firmware version %s", version.c_str());
|
||||
}
|
||||
WiFiOTA::initialize();
|
||||
#endif
|
||||
|
||||
// enableModemSleep();
|
||||
|
||||
198
src/platform/stm32wl/LittleFS.cpp
Normal file
198
src/platform/stm32wl/LittleFS.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 hathach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "LittleFS.h"
|
||||
#include "stm32wlxx_hal_flash.h"
|
||||
|
||||
/**********************************************************************************************************************
|
||||
* Macro definitions
|
||||
**********************************************************************************************************************/
|
||||
/** This macro is used to suppress compiler messages about a parameter not being used in a function. */
|
||||
#define LFS_UNUSED(p) (void)((p))
|
||||
|
||||
#define STM32WL_PAGE_SIZE (FLASH_PAGE_SIZE)
|
||||
#define STM32WL_PAGE_COUNT (FLASH_PAGE_NB)
|
||||
#define STM32WL_FLASH_BASE (FLASH_BASE)
|
||||
|
||||
/*
|
||||
* FLASH_SIZE from stm32wle5xx.h will read the actual FLASH size from the chip.
|
||||
* FLASH_END_ADDR is calculated from FLASH_SIZE.
|
||||
* Use the last 28 KiB of the FLASH
|
||||
*/
|
||||
#define LFS_FLASH_TOTAL_SIZE (14 * 2048) /* needs to be a multiple of LFS_BLOCK_SIZE */
|
||||
#define LFS_BLOCK_SIZE (2048)
|
||||
#define LFS_FLASH_ADDR_END (FLASH_END_ADDR)
|
||||
#define LFS_FLASH_ADDR_BASE (LFS_FLASH_ADDR_END - LFS_FLASH_TOTAL_SIZE + 1)
|
||||
|
||||
#if !CFG_DEBUG
|
||||
#define _LFS_DBG(fmt, ...)
|
||||
#else
|
||||
#define _LFS_DBG(fmt, ...) printf("%s:%d (%s): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// LFS Disk IO
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
|
||||
{
|
||||
LFS_UNUSED(c);
|
||||
|
||||
if (!buffer || !size) {
|
||||
_LFS_DBG("%s Invalid parameter!\r\n", __func__);
|
||||
return LFS_ERR_INVAL;
|
||||
}
|
||||
|
||||
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
|
||||
|
||||
memcpy(buffer, (void *)address, size);
|
||||
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
// Program a region in a block. The block must have previously
|
||||
// been erased. Negative error codes are propogated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
|
||||
{
|
||||
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
|
||||
HAL_StatusTypeDef hal_rc = HAL_OK;
|
||||
uint32_t dw_count = size / 8;
|
||||
uint64_t *bufp = (uint64_t *)buffer;
|
||||
|
||||
LFS_UNUSED(c);
|
||||
|
||||
_LFS_DBG("Programming %d bytes/%d doublewords at address 0x%08x/block %d, offset %d.", size, dw_count, address, block, off);
|
||||
if (HAL_FLASH_Unlock() != HAL_OK) {
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
for (uint32_t i = 0; i < dw_count; i++) {
|
||||
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
|
||||
_LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x.\n", address);
|
||||
HAL_FLASH_Lock();
|
||||
return LFS_ERR_INVAL;
|
||||
}
|
||||
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *bufp);
|
||||
if (hal_rc != HAL_OK) {
|
||||
/* Error occurred while writing data in Flash memory.
|
||||
* User can add here some code to deal with this error.
|
||||
*/
|
||||
_LFS_DBG("Program error at (0x%08x), 0x%X, error: 0x%08x\n", address, hal_rc, HAL_FLASH_GetError());
|
||||
}
|
||||
address += 8;
|
||||
bufp += 1;
|
||||
}
|
||||
if (HAL_FLASH_Lock() != HAL_OK) {
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
|
||||
}
|
||||
|
||||
// Erase a block. A block must be erased before being programmed.
|
||||
// The state of an erased block is undefined. Negative error codes
|
||||
// are propogated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
|
||||
{
|
||||
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE);
|
||||
HAL_StatusTypeDef hal_rc;
|
||||
FLASH_EraseInitTypeDef EraseInitStruct = {.TypeErase = FLASH_TYPEERASE_PAGES, .Page = 0, .NbPages = 1};
|
||||
uint32_t PAGEError = 0;
|
||||
|
||||
LFS_UNUSED(c);
|
||||
|
||||
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
|
||||
_LFS_DBG("Wanted to erase out of bound of FLASH: 0x%08x.\n", address);
|
||||
return LFS_ERR_INVAL;
|
||||
}
|
||||
/* calculate the absolute page, i.e. what the ST wants */
|
||||
EraseInitStruct.Page = (address - STM32WL_FLASH_BASE) / STM32WL_PAGE_SIZE;
|
||||
_LFS_DBG("Erasing block %d at 0x%08x... ", block, address);
|
||||
HAL_FLASH_Unlock();
|
||||
hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
|
||||
}
|
||||
|
||||
// Sync the state of the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
static int _internal_flash_sync(const struct lfs_config *c)
|
||||
{
|
||||
LFS_UNUSED(c);
|
||||
// write function performs no caching. No need for sync.
|
||||
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
static struct lfs_config _InternalFSConfig = {.context = NULL,
|
||||
|
||||
.read = _internal_flash_read,
|
||||
.prog = _internal_flash_prog,
|
||||
.erase = _internal_flash_erase,
|
||||
.sync = _internal_flash_sync,
|
||||
|
||||
.read_size = LFS_BLOCK_SIZE,
|
||||
.prog_size = LFS_BLOCK_SIZE,
|
||||
.block_size = LFS_BLOCK_SIZE,
|
||||
.block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE,
|
||||
.lookahead = 128,
|
||||
|
||||
.read_buffer = NULL,
|
||||
.prog_buffer = NULL,
|
||||
.lookahead_buffer = NULL,
|
||||
.file_buffer = NULL};
|
||||
|
||||
LittleFS InternalFS;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
LittleFS::LittleFS(void) : STM32_LittleFS(&_InternalFSConfig) {}
|
||||
|
||||
bool LittleFS::begin(void)
|
||||
{
|
||||
if (FLASH_BASE >= LFS_FLASH_ADDR_BASE) {
|
||||
/* There is not enough space on this device for a filesystem. */
|
||||
return false;
|
||||
}
|
||||
// failed to mount, erase all pages then format and mount again
|
||||
if (!STM32_LittleFS::begin()) {
|
||||
// Erase all pages of internal flash region for Filesystem.
|
||||
for (uint32_t addr = LFS_FLASH_ADDR_BASE; addr < (LFS_FLASH_ADDR_END + 1); addr += STM32WL_PAGE_SIZE) {
|
||||
_internal_flash_erase(&_InternalFSConfig, (addr - LFS_FLASH_ADDR_BASE) / STM32WL_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// lfs format
|
||||
this->format();
|
||||
|
||||
// mount again if still failed, give up
|
||||
if (!STM32_LittleFS::begin())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
41
src/platform/stm32wl/LittleFS.h
Normal file
41
src/platform/stm32wl/LittleFS.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 hathach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef INTERNALFILESYSTEM_H_
|
||||
#define INTERNALFILESYSTEM_H_
|
||||
|
||||
#include "STM32_LittleFS.h"
|
||||
|
||||
class LittleFS : public STM32_LittleFS
|
||||
{
|
||||
public:
|
||||
LittleFS(void);
|
||||
|
||||
// overwrite to also perform low level format (sector erase of whole flash region)
|
||||
bool begin(void);
|
||||
};
|
||||
|
||||
extern LittleFS InternalFS;
|
||||
|
||||
#endif /* INTERNALFILESYSTEM_H_ */
|
||||
283
src/platform/stm32wl/STM32_LittleFS.cpp
Normal file
283
src/platform/stm32wl/STM32_LittleFS.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "STM32_LittleFS.h"
|
||||
#include <Arduino.h>
|
||||
#include <string.h>
|
||||
|
||||
#define memclr(buffer, size) memset(buffer, 0, size)
|
||||
#define varclr(_var) memclr(_var, sizeof(*(_var)))
|
||||
|
||||
using namespace STM32_LittleFS_Namespace;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Implementation
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
STM32_LittleFS::STM32_LittleFS(void) : STM32_LittleFS(NULL) {}
|
||||
|
||||
STM32_LittleFS::STM32_LittleFS(struct lfs_config *cfg)
|
||||
{
|
||||
varclr(&_lfs);
|
||||
_lfs_cfg = cfg;
|
||||
_mounted = false;
|
||||
}
|
||||
|
||||
STM32_LittleFS::~STM32_LittleFS() {}
|
||||
|
||||
// Initialize and mount the file system
|
||||
// Return true if mounted successfully else probably corrupted.
|
||||
// User should format the disk and try again
|
||||
bool STM32_LittleFS::begin(struct lfs_config *cfg)
|
||||
{
|
||||
_lockFS();
|
||||
|
||||
bool ret;
|
||||
// not a loop, just an quick way to short-circuit on error
|
||||
do {
|
||||
if (_mounted) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
if (cfg) {
|
||||
_lfs_cfg = cfg;
|
||||
}
|
||||
if (nullptr == _lfs_cfg) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
// actually attempt to mount, and log error if one occurs
|
||||
int err = lfs_mount(&_lfs, _lfs_cfg);
|
||||
PRINT_LFS_ERR(err);
|
||||
_mounted = (err == LFS_ERR_OK);
|
||||
ret = _mounted;
|
||||
} while (0);
|
||||
|
||||
_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Tear down and unmount file system
|
||||
void STM32_LittleFS::end(void)
|
||||
{
|
||||
_lockFS();
|
||||
|
||||
if (_mounted) {
|
||||
_mounted = false;
|
||||
int err = lfs_unmount(&_lfs);
|
||||
PRINT_LFS_ERR(err);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
_unlockFS();
|
||||
}
|
||||
|
||||
bool STM32_LittleFS::format(void)
|
||||
{
|
||||
_lockFS();
|
||||
|
||||
int err = LFS_ERR_OK;
|
||||
bool attemptMount = _mounted;
|
||||
// not a loop, just an quick way to short-circuit on error
|
||||
do {
|
||||
// if already mounted: umount first -> format -> remount
|
||||
if (_mounted) {
|
||||
_mounted = false;
|
||||
err = lfs_unmount(&_lfs);
|
||||
if (LFS_ERR_OK != err) {
|
||||
PRINT_LFS_ERR(err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = lfs_format(&_lfs, _lfs_cfg);
|
||||
if (LFS_ERR_OK != err) {
|
||||
PRINT_LFS_ERR(err);
|
||||
break;
|
||||
}
|
||||
|
||||
if (attemptMount) {
|
||||
err = lfs_mount(&_lfs, _lfs_cfg);
|
||||
if (LFS_ERR_OK != err) {
|
||||
PRINT_LFS_ERR(err);
|
||||
break;
|
||||
}
|
||||
_mounted = true;
|
||||
}
|
||||
// success!
|
||||
} while (0);
|
||||
|
||||
_unlockFS();
|
||||
return LFS_ERR_OK == err;
|
||||
}
|
||||
|
||||
// Open a file or folder
|
||||
STM32_LittleFS_Namespace::File STM32_LittleFS::open(char const *filepath, uint8_t mode)
|
||||
{
|
||||
// No lock is required here ... the File() object will synchronize with the mutex provided
|
||||
return STM32_LittleFS_Namespace::File(filepath, mode, *this);
|
||||
}
|
||||
|
||||
// Check if file or folder exists
|
||||
bool STM32_LittleFS::exists(char const *filepath)
|
||||
{
|
||||
struct lfs_info info;
|
||||
_lockFS();
|
||||
|
||||
bool ret = (0 == lfs_stat(&_lfs, filepath, &info));
|
||||
|
||||
_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Create a directory, create intermediate parent if needed
|
||||
bool STM32_LittleFS::mkdir(char const *filepath)
|
||||
{
|
||||
bool ret = true;
|
||||
const char *slash = filepath;
|
||||
if (slash[0] == '/')
|
||||
slash++; // skip root '/'
|
||||
|
||||
_lockFS();
|
||||
|
||||
// make intermediate parent directory(ies)
|
||||
while (NULL != (slash = strchr(slash, '/'))) {
|
||||
char parent[slash - filepath + 1] = {0};
|
||||
memcpy(parent, filepath, slash - filepath);
|
||||
|
||||
int rc = lfs_mkdir(&_lfs, parent);
|
||||
if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) {
|
||||
PRINT_LFS_ERR(rc);
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
slash++;
|
||||
}
|
||||
// make the final requested directory
|
||||
if (ret) {
|
||||
int rc = lfs_mkdir(&_lfs, filepath);
|
||||
if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) {
|
||||
PRINT_LFS_ERR(rc);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Remove a file
|
||||
bool STM32_LittleFS::remove(char const *filepath)
|
||||
{
|
||||
_lockFS();
|
||||
|
||||
int err = lfs_remove(&_lfs, filepath);
|
||||
PRINT_LFS_ERR(err);
|
||||
|
||||
_unlockFS();
|
||||
return LFS_ERR_OK == err;
|
||||
}
|
||||
|
||||
// Rename a file
|
||||
bool STM32_LittleFS::rename(char const *oldfilepath, char const *newfilepath)
|
||||
{
|
||||
_lockFS();
|
||||
|
||||
int err = lfs_rename(&_lfs, oldfilepath, newfilepath);
|
||||
PRINT_LFS_ERR(err);
|
||||
|
||||
_unlockFS();
|
||||
return LFS_ERR_OK == err;
|
||||
}
|
||||
|
||||
// Remove a folder
|
||||
bool STM32_LittleFS::rmdir(char const *filepath)
|
||||
{
|
||||
_lockFS();
|
||||
|
||||
int err = lfs_remove(&_lfs, filepath);
|
||||
PRINT_LFS_ERR(err);
|
||||
|
||||
_unlockFS();
|
||||
return LFS_ERR_OK == err;
|
||||
}
|
||||
|
||||
// Remove a folder recursively
|
||||
bool STM32_LittleFS::rmdir_r(char const *filepath)
|
||||
{
|
||||
/* lfs is modified to remove non-empty folder,
|
||||
According to below issue, comment these 2 line won't corrupt filesystem
|
||||
at least when using LFS v1. If moving to LFS v2, see tracked issue
|
||||
to see if issues (such as the orphans in threaded linked list) are resolved.
|
||||
https://github.com/ARMmbed/littlefs/issues/43
|
||||
*/
|
||||
_lockFS();
|
||||
|
||||
int err = lfs_remove(&_lfs, filepath);
|
||||
PRINT_LFS_ERR(err);
|
||||
|
||||
_unlockFS();
|
||||
return LFS_ERR_OK == err;
|
||||
}
|
||||
|
||||
//------------- Debug -------------//
|
||||
#if CFG_DEBUG
|
||||
|
||||
const char *dbg_strerr_lfs(int32_t err)
|
||||
{
|
||||
switch (err) {
|
||||
case LFS_ERR_OK:
|
||||
return "LFS_ERR_OK";
|
||||
case LFS_ERR_IO:
|
||||
return "LFS_ERR_IO";
|
||||
case LFS_ERR_CORRUPT:
|
||||
return "LFS_ERR_CORRUPT";
|
||||
case LFS_ERR_NOENT:
|
||||
return "LFS_ERR_NOENT";
|
||||
case LFS_ERR_EXIST:
|
||||
return "LFS_ERR_EXIST";
|
||||
case LFS_ERR_NOTDIR:
|
||||
return "LFS_ERR_NOTDIR";
|
||||
case LFS_ERR_ISDIR:
|
||||
return "LFS_ERR_ISDIR";
|
||||
case LFS_ERR_NOTEMPTY:
|
||||
return "LFS_ERR_NOTEMPTY";
|
||||
case LFS_ERR_BADF:
|
||||
return "LFS_ERR_BADF";
|
||||
case LFS_ERR_INVAL:
|
||||
return "LFS_ERR_INVAL";
|
||||
case LFS_ERR_NOSPC:
|
||||
return "LFS_ERR_NOSPC";
|
||||
case LFS_ERR_NOMEM:
|
||||
return "LFS_ERR_NOMEM";
|
||||
|
||||
default:
|
||||
static char errcode[10];
|
||||
sprintf(errcode, "%ld", err);
|
||||
return errcode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
107
src/platform/stm32wl/STM32_LittleFS.h
Normal file
107
src/platform/stm32wl/STM32_LittleFS.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STM32_LITTLEFS_H_
|
||||
#define STM32_LITTLEFS_H_
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
// Internal Flash uses ARM Little FileSystem
|
||||
// https://github.com/ARMmbed/littlefs
|
||||
#include "../../freertosinc.h" // tied to FreeRTOS for serialization
|
||||
#include "STM32_LittleFS_File.h"
|
||||
#include "littlefs/lfs.h"
|
||||
|
||||
class STM32_LittleFS
|
||||
{
|
||||
public:
|
||||
STM32_LittleFS(void);
|
||||
STM32_LittleFS(struct lfs_config *cfg);
|
||||
virtual ~STM32_LittleFS();
|
||||
|
||||
bool begin(struct lfs_config *cfg = NULL);
|
||||
void end(void);
|
||||
|
||||
// Open the specified file/directory with the supplied mode (e.g. read or
|
||||
// write, etc). Returns a File object for interacting with the file.
|
||||
// Note that currently only one file can be open at a time.
|
||||
STM32_LittleFS_Namespace::File open(char const *filename, uint8_t mode = STM32_LittleFS_Namespace::FILE_O_READ);
|
||||
|
||||
// Methods to determine if the requested file path exists.
|
||||
bool exists(char const *filepath);
|
||||
|
||||
// Create the requested directory hierarchy--if intermediate directories
|
||||
// do not exist they will be created.
|
||||
bool mkdir(char const *filepath);
|
||||
|
||||
// Delete the file.
|
||||
bool remove(char const *filepath);
|
||||
|
||||
// Rename the file.
|
||||
bool rename(char const *oldfilepath, char const *newfilepath);
|
||||
|
||||
// Delete a folder (must be empty)
|
||||
bool rmdir(char const *filepath);
|
||||
|
||||
// Delete a folder (recursively)
|
||||
bool rmdir_r(char const *filepath);
|
||||
|
||||
// format file system
|
||||
bool format(void);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* INTERNAL USAGE ONLY
|
||||
* Although declare as public, it is meant to be invoked by internal
|
||||
* code. User should not call these directly
|
||||
*------------------------------------------------------------------*/
|
||||
lfs_t *_getFS(void) { return &_lfs; }
|
||||
void _lockFS(void)
|
||||
{ /* no-op */
|
||||
}
|
||||
void _unlockFS(void)
|
||||
{ /* no-op */
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _mounted;
|
||||
struct lfs_config *_lfs_cfg;
|
||||
lfs_t _lfs;
|
||||
};
|
||||
|
||||
#if !CFG_DEBUG
|
||||
#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, NULL)
|
||||
#define PRINT_LFS_ERR(_err)
|
||||
#else
|
||||
#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, dbg_strerr_lfs)
|
||||
#define PRINT_LFS_ERR(_err) \
|
||||
do { \
|
||||
if (_err) { \
|
||||
printf("%s:%d, LFS error: %d\n", __FILE__, __LINE__, _err); \
|
||||
} \
|
||||
} while (0) // LFS_ERR are of type int, VERIFY_MESS expects long_int
|
||||
|
||||
const char *dbg_strerr_lfs(int32_t err);
|
||||
#endif
|
||||
|
||||
#endif /* STM32_LITTLEFS_H_ */
|
||||
394
src/platform/stm32wl/STM32_LittleFS_File.cpp
Normal file
394
src/platform/stm32wl/STM32_LittleFS_File.cpp
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "STM32_LittleFS.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#define rtos_malloc malloc
|
||||
#define rtos_free free
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
using namespace STM32_LittleFS_Namespace;
|
||||
|
||||
File::File(STM32_LittleFS &fs)
|
||||
{
|
||||
_fs = &fs;
|
||||
_is_dir = false;
|
||||
_name[0] = 0;
|
||||
_name[LFS_NAME_MAX] = 0;
|
||||
_dir_path = NULL;
|
||||
|
||||
_dir = NULL;
|
||||
_file = NULL;
|
||||
}
|
||||
|
||||
File::File(char const *filename, uint8_t mode, STM32_LittleFS &fs) : File(fs)
|
||||
{
|
||||
// public constructor calls public API open(), which will obtain the mutex
|
||||
this->open(filename, mode);
|
||||
}
|
||||
|
||||
bool File::_open_file(char const *filepath, uint8_t mode)
|
||||
{
|
||||
int flags = (mode == FILE_O_READ) ? LFS_O_RDONLY : (mode == FILE_O_WRITE) ? (LFS_O_RDWR | LFS_O_CREAT) : 0;
|
||||
|
||||
if (flags) {
|
||||
_file = (lfs_file_t *)rtos_malloc(sizeof(lfs_file_t));
|
||||
if (!_file)
|
||||
return false;
|
||||
|
||||
int rc = lfs_file_open(_fs->_getFS(), _file, filepath, flags);
|
||||
|
||||
if (rc) {
|
||||
// failed to open
|
||||
PRINT_LFS_ERR(rc);
|
||||
// free memory
|
||||
rtos_free(_file);
|
||||
_file = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// move to end of file
|
||||
if (mode == FILE_O_WRITE)
|
||||
lfs_file_seek(_fs->_getFS(), _file, 0, LFS_SEEK_END);
|
||||
|
||||
_is_dir = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::_open_dir(char const *filepath)
|
||||
{
|
||||
_dir = (lfs_dir_t *)rtos_malloc(sizeof(lfs_dir_t));
|
||||
if (!_dir)
|
||||
return false;
|
||||
|
||||
int rc = lfs_dir_open(_fs->_getFS(), _dir, filepath);
|
||||
|
||||
if (rc) {
|
||||
// failed to open
|
||||
PRINT_LFS_ERR(rc);
|
||||
// free memory
|
||||
rtos_free(_dir);
|
||||
_dir = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
_is_dir = true;
|
||||
|
||||
_dir_path = (char *)rtos_malloc(strlen(filepath) + 1);
|
||||
strcpy(_dir_path, filepath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::open(char const *filepath, uint8_t mode)
|
||||
{
|
||||
bool ret = false;
|
||||
_fs->_lockFS();
|
||||
|
||||
ret = this->_open(filepath, mode);
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool File::_open(char const *filepath, uint8_t mode)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
// close if currently opened
|
||||
if (this->isOpen())
|
||||
_close();
|
||||
|
||||
struct lfs_info info;
|
||||
int rc = lfs_stat(_fs->_getFS(), filepath, &info);
|
||||
|
||||
if (LFS_ERR_OK == rc) {
|
||||
// file existed, open file or directory accordingly
|
||||
ret = (info.type == LFS_TYPE_REG) ? _open_file(filepath, mode) : _open_dir(filepath);
|
||||
} else if (LFS_ERR_NOENT == rc) {
|
||||
// file not existed, only proceed with FILE_O_WRITE mode
|
||||
if (mode == FILE_O_WRITE)
|
||||
ret = _open_file(filepath, mode);
|
||||
} else {
|
||||
PRINT_LFS_ERR(rc);
|
||||
}
|
||||
|
||||
// save bare file name
|
||||
if (ret) {
|
||||
char const *splash = strrchr(filepath, '/');
|
||||
strncpy(_name, splash ? (splash + 1) : filepath, LFS_NAME_MAX);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t File::write(uint8_t ch)
|
||||
{
|
||||
return write(&ch, 1);
|
||||
}
|
||||
|
||||
size_t File::write(uint8_t const *buf, size_t size)
|
||||
{
|
||||
lfs_ssize_t wrcount = 0;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
wrcount = lfs_file_write(_fs->_getFS(), _file, buf, size);
|
||||
if (wrcount < 0) {
|
||||
wrcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return wrcount;
|
||||
}
|
||||
|
||||
int File::read(void)
|
||||
{
|
||||
// this thin wrapper relies on called function to synchronize
|
||||
int ret = -1;
|
||||
uint8_t ch;
|
||||
if (read(&ch, 1) > 0) {
|
||||
ret = static_cast<int>(ch);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int File::read(void *buf, uint16_t nbyte)
|
||||
{
|
||||
int ret = 0;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
ret = lfs_file_read(_fs->_getFS(), _file, buf, nbyte);
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int File::peek(void)
|
||||
{
|
||||
int ret = -1;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
uint32_t pos = lfs_file_tell(_fs->_getFS(), _file);
|
||||
uint8_t ch = 0;
|
||||
if (lfs_file_read(_fs->_getFS(), _file, &ch, 1) > 0) {
|
||||
ret = static_cast<int>(ch);
|
||||
}
|
||||
(void)lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET);
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int File::available(void)
|
||||
{
|
||||
int ret = 0;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
uint32_t size = lfs_file_size(_fs->_getFS(), _file);
|
||||
uint32_t pos = lfs_file_tell(_fs->_getFS(), _file);
|
||||
ret = size - pos;
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool File::seek(uint32_t pos)
|
||||
{
|
||||
bool ret = false;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
ret = lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET) >= 0;
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t File::position(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
ret = lfs_file_tell(_fs->_getFS(), _file);
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t File::size(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
ret = lfs_file_size(_fs->_getFS(), _file);
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool File::truncate(uint32_t pos)
|
||||
{
|
||||
int32_t ret = LFS_ERR_ISDIR;
|
||||
_fs->_lockFS();
|
||||
if (!this->_is_dir) {
|
||||
ret = lfs_file_truncate(_fs->_getFS(), _file, pos);
|
||||
}
|
||||
_fs->_unlockFS();
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
bool File::truncate(void)
|
||||
{
|
||||
int32_t ret = LFS_ERR_ISDIR;
|
||||
uint32_t pos;
|
||||
_fs->_lockFS();
|
||||
if (!this->_is_dir) {
|
||||
pos = lfs_file_tell(_fs->_getFS(), _file);
|
||||
ret = lfs_file_truncate(_fs->_getFS(), _file, pos);
|
||||
}
|
||||
_fs->_unlockFS();
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
void File::flush(void)
|
||||
{
|
||||
_fs->_lockFS();
|
||||
|
||||
if (!this->_is_dir) {
|
||||
lfs_file_sync(_fs->_getFS(), _file);
|
||||
}
|
||||
|
||||
_fs->_unlockFS();
|
||||
return;
|
||||
}
|
||||
|
||||
void File::close(void)
|
||||
{
|
||||
_fs->_lockFS();
|
||||
this->_close();
|
||||
_fs->_unlockFS();
|
||||
}
|
||||
|
||||
void File::_close(void)
|
||||
{
|
||||
if (this->isOpen()) {
|
||||
if (this->_is_dir) {
|
||||
lfs_dir_close(_fs->_getFS(), _dir);
|
||||
rtos_free(_dir);
|
||||
_dir = NULL;
|
||||
|
||||
if (this->_dir_path)
|
||||
rtos_free(_dir_path);
|
||||
_dir_path = NULL;
|
||||
} else {
|
||||
lfs_file_close(this->_fs->_getFS(), _file);
|
||||
rtos_free(_file);
|
||||
_file = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File::operator bool(void)
|
||||
{
|
||||
return isOpen();
|
||||
}
|
||||
|
||||
bool File::isOpen(void)
|
||||
{
|
||||
return (_file != NULL) || (_dir != NULL);
|
||||
}
|
||||
|
||||
// WARNING -- although marked as `const`, the values pointed
|
||||
// to may change. For example, if the same File
|
||||
// object has `open()` called with a different
|
||||
// file or directory name, this same pointer will
|
||||
// suddenly (unexpectedly?) have different values.
|
||||
char const *File::name(void)
|
||||
{
|
||||
return this->_name;
|
||||
}
|
||||
|
||||
bool File::isDirectory(void)
|
||||
{
|
||||
return this->_is_dir;
|
||||
}
|
||||
|
||||
File File::openNextFile(uint8_t mode)
|
||||
{
|
||||
_fs->_lockFS();
|
||||
|
||||
File ret(*_fs);
|
||||
if (this->_is_dir) {
|
||||
struct lfs_info info;
|
||||
int rc;
|
||||
|
||||
// lfs_dir_read returns 0 when reaching end of directory, 1 if found an entry
|
||||
// Skip the "." and ".." entries ...
|
||||
do {
|
||||
rc = lfs_dir_read(_fs->_getFS(), _dir, &info);
|
||||
} while (rc == 1 && (!strcmp(".", info.name) || !strcmp("..", info.name)));
|
||||
|
||||
if (rc == 1) {
|
||||
// string cat name with current folder
|
||||
char filepath[strlen(_dir_path) + 1 + strlen(info.name) + 1]; // potential for significant stack usage
|
||||
strcpy(filepath, _dir_path);
|
||||
if (!(_dir_path[0] == '/' && _dir_path[1] == 0))
|
||||
strcat(filepath, "/"); // only add '/' if cwd is not root
|
||||
strcat(filepath, info.name);
|
||||
|
||||
(void)ret._open(filepath, mode); // return value is ignored ... caller is expected to check isOpened()
|
||||
} else if (rc < 0) {
|
||||
PRINT_LFS_ERR(rc);
|
||||
}
|
||||
}
|
||||
_fs->_unlockFS();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void File::rewindDirectory(void)
|
||||
{
|
||||
_fs->_lockFS();
|
||||
if (this->_is_dir) {
|
||||
lfs_dir_rewind(_fs->_getFS(), _dir);
|
||||
}
|
||||
_fs->_unlockFS();
|
||||
}
|
||||
108
src/platform/stm32wl/STM32_LittleFS_File.h
Normal file
108
src/platform/stm32wl/STM32_LittleFS_File.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STM32_LITTLEFS_FILE_H_
|
||||
#define STM32_LITTLEFS_FILE_H_
|
||||
|
||||
#include "littlefs/lfs.h"
|
||||
|
||||
// Forward declaration
|
||||
class STM32_LittleFS;
|
||||
|
||||
namespace STM32_LittleFS_Namespace
|
||||
{
|
||||
|
||||
// avoid conflict with other FileSystem FILE_READ/FILE_WRITE
|
||||
enum {
|
||||
FILE_O_READ = 0,
|
||||
FILE_O_WRITE = 1,
|
||||
};
|
||||
|
||||
class File : public Stream
|
||||
{
|
||||
public:
|
||||
File(STM32_LittleFS &fs);
|
||||
File(char const *filename, uint8_t mode, STM32_LittleFS &fs);
|
||||
|
||||
public:
|
||||
bool open(char const *filename, uint8_t mode);
|
||||
|
||||
//------------- Stream API -------------//
|
||||
virtual size_t write(uint8_t ch);
|
||||
virtual size_t write(uint8_t const *buf, size_t size);
|
||||
size_t write(const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); }
|
||||
|
||||
virtual int read(void);
|
||||
int read(void *buf, uint16_t nbyte);
|
||||
|
||||
virtual int peek(void);
|
||||
virtual int available(void);
|
||||
virtual void flush(void);
|
||||
|
||||
bool seek(uint32_t pos);
|
||||
uint32_t position(void);
|
||||
uint32_t size(void);
|
||||
|
||||
bool truncate(uint32_t pos);
|
||||
bool truncate(void);
|
||||
|
||||
void close(void);
|
||||
|
||||
operator bool(void);
|
||||
|
||||
bool isOpen(void);
|
||||
char const *name(void);
|
||||
|
||||
bool isDirectory(void);
|
||||
File openNextFile(uint8_t mode = FILE_O_READ);
|
||||
void rewindDirectory(void);
|
||||
|
||||
private:
|
||||
STM32_LittleFS *_fs;
|
||||
|
||||
bool _is_dir;
|
||||
|
||||
union {
|
||||
lfs_file_t *_file;
|
||||
lfs_dir_t *_dir;
|
||||
};
|
||||
|
||||
char *_dir_path;
|
||||
char _name[LFS_NAME_MAX + 1];
|
||||
|
||||
bool _open(char const *filepath, uint8_t mode);
|
||||
bool _open_file(char const *filepath, uint8_t mode);
|
||||
bool _open_dir(char const *filepath);
|
||||
void _close(void);
|
||||
};
|
||||
|
||||
} // namespace STM32_LittleFS_Namespace
|
||||
|
||||
#endif /* STM32_LITTLEFS_FILE_H_ */
|
||||
2531
src/platform/stm32wl/littlefs/lfs.c
Normal file
2531
src/platform/stm32wl/littlefs/lfs.c
Normal file
File diff suppressed because it is too large
Load Diff
476
src/platform/stm32wl/littlefs/lfs.h
Normal file
476
src/platform/stm32wl/littlefs/lfs.h
Normal file
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* The little filesystem
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef LFS_H
|
||||
#define LFS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Version info ///
|
||||
|
||||
// Software library version
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS_VERSION 0x00010006
|
||||
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
||||
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
||||
|
||||
// Version of On-disk data structures
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS_DISK_VERSION 0x00010001
|
||||
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
||||
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
||||
|
||||
/// Definitions ///
|
||||
|
||||
// Type definitions
|
||||
typedef uint32_t lfs_size_t;
|
||||
typedef uint32_t lfs_off_t;
|
||||
|
||||
typedef int32_t lfs_ssize_t;
|
||||
typedef int32_t lfs_soff_t;
|
||||
|
||||
typedef uint32_t lfs_block_t;
|
||||
|
||||
// Max name size in bytes
|
||||
#ifndef LFS_NAME_MAX
|
||||
#define LFS_NAME_MAX 255
|
||||
#endif
|
||||
|
||||
// Possible error codes, these are negative to allow
|
||||
// valid positive return values
|
||||
enum lfs_error {
|
||||
LFS_ERR_OK = 0, // No error
|
||||
LFS_ERR_IO = -5, // Error during device operation
|
||||
LFS_ERR_CORRUPT = -52, // Corrupted
|
||||
LFS_ERR_NOENT = -2, // No directory entry
|
||||
LFS_ERR_EXIST = -17, // Entry already exists
|
||||
LFS_ERR_NOTDIR = -20, // Entry is not a dir
|
||||
LFS_ERR_ISDIR = -21, // Entry is a dir
|
||||
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
|
||||
LFS_ERR_BADF = -9, // Bad file number
|
||||
LFS_ERR_INVAL = -22, // Invalid parameter
|
||||
LFS_ERR_NOSPC = -28, // No space left on device
|
||||
LFS_ERR_NOMEM = -12, // No more memory available
|
||||
};
|
||||
|
||||
// File types
|
||||
enum lfs_type {
|
||||
LFS_TYPE_REG = 0x11,
|
||||
LFS_TYPE_DIR = 0x22,
|
||||
LFS_TYPE_SUPERBLOCK = 0x2e,
|
||||
};
|
||||
|
||||
// File open flags
|
||||
enum lfs_open_flags {
|
||||
// open flags
|
||||
LFS_O_RDONLY = 1, // Open a file as read only
|
||||
LFS_O_WRONLY = 2, // Open a file as write only
|
||||
LFS_O_RDWR = 3, // Open a file as read and write
|
||||
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
||||
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
||||
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
||||
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
||||
|
||||
// internally used flags
|
||||
LFS_F_DIRTY = 0x10000, // File does not match storage
|
||||
LFS_F_WRITING = 0x20000, // File has been written since last flush
|
||||
LFS_F_READING = 0x40000, // File has been read since last flush
|
||||
LFS_F_ERRED = 0x80000, // An error occured during write
|
||||
};
|
||||
|
||||
// File seek flags
|
||||
enum lfs_whence_flags {
|
||||
LFS_SEEK_SET = 0, // Seek relative to an absolute position
|
||||
LFS_SEEK_CUR = 1, // Seek relative to the current file position
|
||||
LFS_SEEK_END = 2, // Seek relative to the end of the file
|
||||
};
|
||||
|
||||
// Configuration provided during initialization of the littlefs
|
||||
struct lfs_config {
|
||||
// Opaque user provided context that can be used to pass
|
||||
// information to the block device operations
|
||||
void *context;
|
||||
|
||||
// Read a region in a block. Negative error codes are propogated
|
||||
// to the user.
|
||||
int (*read)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
|
||||
|
||||
// Program a region in a block. The block must have previously
|
||||
// been erased. Negative error codes are propogated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
int (*prog)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||
|
||||
// Erase a block. A block must be erased before being programmed.
|
||||
// The state of an erased block is undefined. Negative error codes
|
||||
// are propogated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
int (*erase)(const struct lfs_config *c, lfs_block_t block);
|
||||
|
||||
// Sync the state of the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
int (*sync)(const struct lfs_config *c);
|
||||
|
||||
// Minimum size of a block read. This determines the size of read buffers.
|
||||
// This may be larger than the physical read size to improve performance
|
||||
// by caching more of the block device.
|
||||
lfs_size_t read_size;
|
||||
|
||||
// Minimum size of a block program. This determines the size of program
|
||||
// buffers. This may be larger than the physical program size to improve
|
||||
// performance by caching more of the block device.
|
||||
// Must be a multiple of the read size.
|
||||
lfs_size_t prog_size;
|
||||
|
||||
// Size of an erasable block. This does not impact ram consumption and
|
||||
// may be larger than the physical erase size. However, this should be
|
||||
// kept small as each file currently takes up an entire block.
|
||||
// Must be a multiple of the program size.
|
||||
lfs_size_t block_size;
|
||||
|
||||
// Number of erasable blocks on the device.
|
||||
lfs_size_t block_count;
|
||||
|
||||
// Number of blocks to lookahead during block allocation. A larger
|
||||
// lookahead reduces the number of passes required to allocate a block.
|
||||
// The lookahead buffer requires only 1 bit per block so it can be quite
|
||||
// large with little ram impact. Should be a multiple of 32.
|
||||
lfs_size_t lookahead;
|
||||
|
||||
// Optional, statically allocated read buffer. Must be read sized.
|
||||
void *read_buffer;
|
||||
|
||||
// Optional, statically allocated program buffer. Must be program sized.
|
||||
void *prog_buffer;
|
||||
|
||||
// Optional, statically allocated lookahead buffer. Must be 1 bit per
|
||||
// lookahead block.
|
||||
void *lookahead_buffer;
|
||||
|
||||
// Optional, statically allocated buffer for files. Must be program sized.
|
||||
// If enabled, only one file may be opened at a time.
|
||||
void *file_buffer;
|
||||
};
|
||||
|
||||
// Optional configuration provided during lfs_file_opencfg
|
||||
struct lfs_file_config {
|
||||
// Optional, statically allocated buffer for files. Must be program sized.
|
||||
// If NULL, malloc will be used by default.
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
// File info structure
|
||||
struct lfs_info {
|
||||
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
|
||||
uint8_t type;
|
||||
|
||||
// Size of the file, only valid for REG files
|
||||
lfs_size_t size;
|
||||
|
||||
// Name of the file stored as a null-terminated string
|
||||
char name[LFS_NAME_MAX + 1];
|
||||
};
|
||||
|
||||
/// littlefs data structures ///
|
||||
typedef struct lfs_entry {
|
||||
lfs_off_t off;
|
||||
|
||||
struct lfs_disk_entry {
|
||||
uint8_t type;
|
||||
uint8_t elen;
|
||||
uint8_t alen;
|
||||
uint8_t nlen;
|
||||
union {
|
||||
struct {
|
||||
lfs_block_t head;
|
||||
lfs_size_t size;
|
||||
} file;
|
||||
lfs_block_t dir[2];
|
||||
} u;
|
||||
} d;
|
||||
} lfs_entry_t;
|
||||
|
||||
typedef struct lfs_cache {
|
||||
lfs_block_t block;
|
||||
lfs_off_t off;
|
||||
uint8_t *buffer;
|
||||
} lfs_cache_t;
|
||||
|
||||
typedef struct lfs_file {
|
||||
struct lfs_file *next;
|
||||
lfs_block_t pair[2];
|
||||
lfs_off_t poff;
|
||||
|
||||
lfs_block_t head;
|
||||
lfs_size_t size;
|
||||
|
||||
const struct lfs_file_config *cfg;
|
||||
uint32_t flags;
|
||||
lfs_off_t pos;
|
||||
lfs_block_t block;
|
||||
lfs_off_t off;
|
||||
lfs_cache_t cache;
|
||||
} lfs_file_t;
|
||||
|
||||
typedef struct lfs_dir {
|
||||
struct lfs_dir *next;
|
||||
lfs_block_t pair[2];
|
||||
lfs_off_t off;
|
||||
|
||||
lfs_block_t head[2];
|
||||
lfs_off_t pos;
|
||||
|
||||
struct lfs_disk_dir {
|
||||
uint32_t rev;
|
||||
lfs_size_t size;
|
||||
lfs_block_t tail[2];
|
||||
} d;
|
||||
} lfs_dir_t;
|
||||
|
||||
typedef struct lfs_superblock {
|
||||
lfs_off_t off;
|
||||
|
||||
struct lfs_disk_superblock {
|
||||
uint8_t type;
|
||||
uint8_t elen;
|
||||
uint8_t alen;
|
||||
uint8_t nlen;
|
||||
lfs_block_t root[2];
|
||||
uint32_t block_size;
|
||||
uint32_t block_count;
|
||||
uint32_t version;
|
||||
char magic[8];
|
||||
} d;
|
||||
} lfs_superblock_t;
|
||||
|
||||
typedef struct lfs_free {
|
||||
lfs_block_t off;
|
||||
lfs_block_t size;
|
||||
lfs_block_t i;
|
||||
lfs_block_t ack;
|
||||
uint32_t *buffer;
|
||||
} lfs_free_t;
|
||||
|
||||
// The littlefs type
|
||||
typedef struct lfs {
|
||||
const struct lfs_config *cfg;
|
||||
|
||||
lfs_block_t root[2];
|
||||
lfs_file_t *files;
|
||||
lfs_dir_t *dirs;
|
||||
|
||||
lfs_cache_t rcache;
|
||||
lfs_cache_t pcache;
|
||||
|
||||
lfs_free_t free;
|
||||
bool deorphaned;
|
||||
} lfs_t;
|
||||
|
||||
/// Filesystem functions ///
|
||||
|
||||
// Format a block device with the littlefs
|
||||
//
|
||||
// Requires a littlefs object and config struct. This clobbers the littlefs
|
||||
// object, and does not leave the filesystem mounted. The config struct must
|
||||
// be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
||||
|
||||
// Mounts a littlefs
|
||||
//
|
||||
// Requires a littlefs object and config struct. Multiple filesystems
|
||||
// may be mounted simultaneously with multiple littlefs objects. Both
|
||||
// lfs and config must be allocated while mounted. The config struct must
|
||||
// be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
||||
|
||||
// Unmounts a littlefs
|
||||
//
|
||||
// Does nothing besides releasing any allocated resources.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_unmount(lfs_t *lfs);
|
||||
|
||||
/// General operations ///
|
||||
|
||||
// Removes a file or directory
|
||||
//
|
||||
// If removing a directory, the directory must be empty.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_remove(lfs_t *lfs, const char *path);
|
||||
|
||||
// Rename or move a file or directory
|
||||
//
|
||||
// If the destination exists, it must match the source in type.
|
||||
// If the destination is a directory, the directory must be empty.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
|
||||
|
||||
// Find info about a file or directory
|
||||
//
|
||||
// Fills out the info structure, based on the specified file or directory.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
||||
|
||||
/// File operations ///
|
||||
|
||||
// Open a file
|
||||
//
|
||||
// The mode that the file is opened in is determined by the flags, which
|
||||
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags);
|
||||
|
||||
// Open a file with extra configuration
|
||||
//
|
||||
// The mode that the file is opened in is determined by the flags, which
|
||||
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||
//
|
||||
// The config struct provides additional config options per file as described
|
||||
// above. The config struct must be allocated while the file is open, and the
|
||||
// config struct must be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, const char *path, int flags, const struct lfs_file_config *config);
|
||||
|
||||
// Close a file
|
||||
//
|
||||
// Any pending writes are written out to storage as though
|
||||
// sync had been called and releases any allocated resources.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Synchronize a file on storage
|
||||
//
|
||||
// Any pending writes are written out to storage.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Read data from file
|
||||
//
|
||||
// Takes a buffer and size indicating where to store the read data.
|
||||
// Returns the number of bytes read, or a negative error code on failure.
|
||||
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, void *buffer, lfs_size_t size);
|
||||
|
||||
// Write data to file
|
||||
//
|
||||
// Takes a buffer and size indicating the data to write. The file will not
|
||||
// actually be updated on the storage until either sync or close is called.
|
||||
//
|
||||
// Returns the number of bytes written, or a negative error code on failure.
|
||||
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, const void *buffer, lfs_size_t size);
|
||||
|
||||
// Change the position of the file
|
||||
//
|
||||
// The change in position is determined by the offset and whence flag.
|
||||
// Returns the old position of the file, or a negative error code on failure.
|
||||
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, lfs_soff_t off, int whence);
|
||||
|
||||
// Truncates the size of the file to the specified size
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
|
||||
|
||||
// Return the position of the file
|
||||
//
|
||||
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||
// Returns the position of the file, or a negative error code on failure.
|
||||
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Change the position of the file to the beginning of the file
|
||||
//
|
||||
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Return the size of the file
|
||||
//
|
||||
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
|
||||
// Returns the size of the file, or a negative error code on failure.
|
||||
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
/// Directory operations ///
|
||||
|
||||
// Create a directory
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_mkdir(lfs_t *lfs, const char *path);
|
||||
|
||||
// Open a directory
|
||||
//
|
||||
// Once open a directory can be used with read to iterate over files.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
|
||||
|
||||
// Close a directory
|
||||
//
|
||||
// Releases any allocated resources.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
// Read an entry in the directory
|
||||
//
|
||||
// Fills out the info structure, based on the specified file or directory.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
|
||||
|
||||
// Change the position of the directory
|
||||
//
|
||||
// The new off must be a value previous returned from tell and specifies
|
||||
// an absolute offset in the directory seek.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
|
||||
|
||||
// Return the position of the directory
|
||||
//
|
||||
// The returned offset is only meant to be consumed by seek and may not make
|
||||
// sense, but does indicate the current position in the directory iteration.
|
||||
//
|
||||
// Returns the position of the directory, or a negative error code on failure.
|
||||
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
// Change the position of the directory to the beginning of the directory
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
/// Miscellaneous littlefs specific operations ///
|
||||
|
||||
// Traverse through all blocks in use by the filesystem
|
||||
//
|
||||
// The provided callback will be called with each block address that is
|
||||
// currently in use by the filesystem. This can be used to determine which
|
||||
// blocks are in use or how much of the storage is available.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data);
|
||||
|
||||
// Prunes any recoverable errors that may have occured in the filesystem
|
||||
//
|
||||
// Not needed to be called by user unless an operation is interrupted
|
||||
// but the filesystem is still mounted. This is already called on first
|
||||
// allocation.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_deorphan(lfs_t *lfs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
28
src/platform/stm32wl/littlefs/lfs_util.c
Normal file
28
src/platform/stm32wl/littlefs/lfs_util.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* lfs util functions
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "lfs_util.h"
|
||||
|
||||
// Only compile if user does not provide custom config
|
||||
#ifndef LFS_CONFIG
|
||||
|
||||
// Software CRC implementation with small lookup table
|
||||
void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size)
|
||||
{
|
||||
static const uint32_t rtable[16] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
||||
};
|
||||
|
||||
const uint8_t *data = buffer;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf];
|
||||
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
199
src/platform/stm32wl/littlefs/lfs_util.h
Normal file
199
src/platform/stm32wl/littlefs/lfs_util.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* lfs utility functions
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef LFS_UTIL_H
|
||||
#define LFS_UTIL_H
|
||||
|
||||
// Users can override lfs_util.h with their own configuration by defining
|
||||
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
|
||||
//
|
||||
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
|
||||
// provided by the config file. To start I would suggest copying lfs_util.h and
|
||||
// modifying as needed.
|
||||
#ifdef LFS_CONFIG
|
||||
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
|
||||
#define LFS_STRINGIZE2(x) #x
|
||||
#include LFS_STRINGIZE(LFS_CONFIG)
|
||||
#else
|
||||
|
||||
// System includes
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef LFS_NO_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifndef LFS_NO_ASSERT
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#if !CFG_DEBUG
|
||||
#define LFS_NO_DEBUG
|
||||
#define LFS_NO_WARN
|
||||
#define LFS_NO_ERROR
|
||||
#endif
|
||||
|
||||
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Macros, may be replaced by system specific wrappers. Arguments to these
|
||||
// macros must not have side-effects as the macros can be removed for a smaller
|
||||
// code footprint
|
||||
|
||||
// Logging functions
|
||||
#ifndef LFS_NO_DEBUG
|
||||
#define LFS_DEBUG(fmt, ...) printf("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LFS_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_WARN
|
||||
#define LFS_WARN(fmt, ...) printf("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LFS_WARN(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_ERROR
|
||||
#define LFS_ERROR(fmt, ...) printf("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LFS_ERROR(fmt, ...)
|
||||
#endif
|
||||
|
||||
// Runtime assertions
|
||||
#ifndef LFS_NO_ASSERT
|
||||
#define LFS_ASSERT(test) assert(test)
|
||||
#else
|
||||
#define LFS_ASSERT(test)
|
||||
#endif
|
||||
|
||||
// Builtin functions, these may be replaced by more efficient
|
||||
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||
// expensive basic C implementation for debugging purposes
|
||||
|
||||
// Min/max functions for unsigned 32-bit numbers
|
||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
// Find the next smallest power of 2 less than or equal to a
|
||||
static inline uint32_t lfs_npw2(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return 32 - __builtin_clz(a - 1);
|
||||
#else
|
||||
uint32_t r = 0;
|
||||
uint32_t s;
|
||||
a -= 1;
|
||||
s = (a > 0xffff) << 4;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
s = (a > 0xff) << 3;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
s = (a > 0xf) << 2;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
s = (a > 0x3) << 1;
|
||||
a >>= s;
|
||||
r |= s;
|
||||
return (r | (a >> 1)) + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of trailing binary zeros in a
|
||||
// lfs_ctz(0) may be undefined
|
||||
static inline uint32_t lfs_ctz(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||
return __builtin_ctz(a);
|
||||
#else
|
||||
return lfs_npw2((a & -a) + 1) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of binary ones in a
|
||||
static inline uint32_t lfs_popc(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return __builtin_popcount(a);
|
||||
#else
|
||||
a = a - ((a >> 1) & 0x55555555);
|
||||
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Find the sequence comparison of a and b, this is the distance
|
||||
// between a and b ignoring overflow
|
||||
static inline int lfs_scmp(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (int)(unsigned)(a - b);
|
||||
}
|
||||
|
||||
// Convert from 32-bit little-endian to native order
|
||||
static inline uint32_t lfs_fromle32(uint32_t a)
|
||||
{
|
||||
#if !defined(LFS_NO_INTRINSICS) && ((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
|
||||
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
return a;
|
||||
#elif !defined(LFS_NO_INTRINSICS) && \
|
||||
((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
return __builtin_bswap32(a);
|
||||
#else
|
||||
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) | (((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Convert to 32-bit little-endian from native order
|
||||
static inline uint32_t lfs_tole32(uint32_t a)
|
||||
{
|
||||
return lfs_fromle32(a);
|
||||
}
|
||||
|
||||
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
|
||||
|
||||
// Allocate memory, only used if buffers are not provided to littlefs
|
||||
static inline void *lfs_malloc(size_t size)
|
||||
{
|
||||
#ifndef LFS_NO_MALLOC
|
||||
return malloc(size);
|
||||
#else
|
||||
(void)size;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||
static inline void lfs_free(void *p)
|
||||
{
|
||||
#ifndef LFS_NO_MALLOC
|
||||
free(p);
|
||||
#else
|
||||
(void)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -32,6 +32,8 @@ void powerCommandsCheck()
|
||||
delete screen;
|
||||
LOG_DEBUG("final reboot!");
|
||||
reboot();
|
||||
#elif defined(ARCH_STM32WL)
|
||||
HAL_NVIC_SystemReset();
|
||||
#else
|
||||
rebootAtMsec = -1;
|
||||
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
|
||||
|
||||
@@ -40,5 +40,9 @@
|
||||
// "USERPREFS_OEM_IMAGE_WIDTH": "50",
|
||||
// "USERPREFS_OEM_IMAGE_HEIGHT": "28",
|
||||
// "USERPREFS_OEM_IMAGE_DATA": "{ 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00, 0x18, 0x1F, 0xF0, 0x67, 0x00, 0x00, 0x00, 0x30, 0x1F, 0xF8, 0x33, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFC, 0x31, 0x00, 0x00, 0x00, 0x60, 0x00, 0xFE, 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x7E, 0x18, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x3F, 0x0C, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x81, 0x1F, 0x06, 0x00, 0x00, 0x00, 0x80, 0xC1, 0x0F, 0x06, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xC7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00}",
|
||||
// "USERPREFS_NETWORK_ENABLED_PROTOCOLS": "1", // Enable UDP mesh
|
||||
// "USERPREFS_NETWORK_WIFI_ENABLED": "true",
|
||||
// "USERPREFS_NETWORK_WIFI_SSID": "wifi_ssid",
|
||||
// "USERPREFS_NETWORK_WIFI_PSK": "wifi_psk",
|
||||
"USERPREFS_TZ_STRING": "tzplaceholder "
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ extends = stm32_base
|
||||
; `ebyte_e77_dev` was added in this commit. Remove when a new release is used in the base.
|
||||
platform = https://github.com/platformio/platform-ststm32.git#3208828db447f4373cd303b7f7393c8fc0dae623
|
||||
board = ebyte_e77_dev
|
||||
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${stm32_base.build_flags}
|
||||
@@ -11,31 +12,19 @@ build_flags =
|
||||
-DPIN_SERIAL_RX=PA3
|
||||
-DPIN_SERIAL_TX=PA2
|
||||
-DHAL_DAC_MODULE_ONLY
|
||||
-DHAL_ADC_MODULE_DISABLED
|
||||
-DHAL_COMP_MODULE_DISABLED
|
||||
-DHAL_CRC_MODULE_DISABLED
|
||||
-DHAL_CRYP_MODULE_DISABLED
|
||||
-DHAL_GTZC_MODULE_DISABLED
|
||||
-DHAL_HSEM_MODULE_DISABLED
|
||||
-DHAL_I2C_MODULE_DISABLED
|
||||
-DHAL_I2S_MODULE_DISABLED
|
||||
-DHAL_IPCC_MODULE_DISABLED
|
||||
-DHAL_IRDA_MODULE_DISABLED
|
||||
-DHAL_IWDG_MODULE_DISABLED
|
||||
-DHAL_LPTIM_MODULE_DISABLED
|
||||
-DHAL_PKA_MODULE_DISABLED
|
||||
-DHAL_RNG_MODULE_DISABLED
|
||||
-DHAL_RTC_MODULE_DISABLED
|
||||
-DHAL_SMARTCARD_MODULE_DISABLED
|
||||
-DHAL_SMBUS_MODULE_DISABLED
|
||||
-DHAL_TIM_MODULE_DISABLED
|
||||
-DHAL_WWDG_MODULE_DISABLED
|
||||
-DHAL_EXTI_MODULE_DISABLED
|
||||
-DHAL_SAI_MODULE_DISABLED
|
||||
-DHAL_ICACHE_MODULE_DISABLED
|
||||
-DHAL_RNG_MODULE_ENABLED
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
; -D PIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
|
||||
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
|
||||
-DMESHTASTIC_EXCLUDE_I2C=1
|
||||
-DMESHTASTIC_EXCLUDE_WIFI=1
|
||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH=1
|
||||
-DMESHTASTIC_EXCLUDE_GPS=1
|
||||
-DMESHTASTIC_EXCLUDE_SCREEN=1
|
||||
-DMESHTASTIC_EXCLUDE_MQTT=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERMON=1
|
||||
;-DPIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
|
||||
;-DCFG_DEBUG
|
||||
|
||||
upload_port = stlink
|
||||
@@ -14,7 +14,6 @@ Do not expect a working Meshtastic device with this target.
|
||||
#define _VARIANT_EBYTE_E77_
|
||||
|
||||
#define USE_STM32WLx
|
||||
#define MAX_NUM_NODES 10
|
||||
|
||||
#define LED_PIN PB4 // LED1
|
||||
// #define LED_PIN PB3 // LED2
|
||||
|
||||
@@ -5,6 +5,7 @@ board_build.flash_mode = qio
|
||||
board_build.psram_type = opi
|
||||
board_upload.flash_size = 8MB
|
||||
board_upload.maximum_size = 8388608
|
||||
board_build.partitions = default_8MB.csv
|
||||
board = esp32-s3-devkitc-1
|
||||
;upload_port = /dev/ttyUSB0
|
||||
board_level = extra
|
||||
@@ -32,6 +33,7 @@ board_build.flash_mode = qio
|
||||
board_build.psram_type = opi
|
||||
board_upload.flash_size = 8MB
|
||||
board_upload.maximum_size = 8388608
|
||||
board_build.partitions = default_8MB.csv
|
||||
board = esp32-s3-devkitc-1
|
||||
;upload_port = /dev/ttyUSB0
|
||||
board_level = extra
|
||||
@@ -59,6 +61,7 @@ board_build.flash_mode = qio
|
||||
board_build.psram_type = opi
|
||||
board_upload.flash_size = 8MB
|
||||
board_upload.maximum_size = 8388608
|
||||
board_build.partitions = default_8MB.csv
|
||||
board = esp32-s3-devkitc-1
|
||||
;upload_port = /dev/ttyUSB0
|
||||
board_level = extra
|
||||
|
||||
@@ -88,6 +88,7 @@ debug_tool = jlink
|
||||
[env:t-energy-s3_e22]
|
||||
extends = esp32s3_base
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = default_16MB.csv
|
||||
board_level = extra
|
||||
board_upload.flash_size = 16MB ;Specify the FLASH capacity as 16MB
|
||||
board_build.arduino.memory_type = qio_opi ;Enable internal PSRAM
|
||||
@@ -100,4 +101,4 @@ build_flags =
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-I variants/diy/t-energy-s3_e22
|
||||
-I variants/diy/t-energy-s3_e22
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[env:dreamcatcher] ; 2301, latest revision
|
||||
extends = esp32s3_base
|
||||
board = esp32s3box
|
||||
board_build.partitions = default_16MB.csv
|
||||
board_level = extra
|
||||
|
||||
build_flags =
|
||||
@@ -8,7 +9,7 @@ build_flags =
|
||||
-D PRIVATE_HW
|
||||
-D OTHERNET_DC_REV=2301
|
||||
-I variants/dreamcatcher
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
|
||||
lib_deps = ${esp32s3_base.lib_deps}
|
||||
earlephilhower/ESP8266Audio@^1.9.9
|
||||
@@ -17,6 +18,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
||||
[env:dreamcatcher-2206]
|
||||
extends = esp32s3_base
|
||||
board = esp32s3box
|
||||
board_build.partitions = default_16MB.csv
|
||||
board_level = extra
|
||||
|
||||
build_flags =
|
||||
@@ -24,4 +26,4 @@ build_flags =
|
||||
-D PRIVATE_HW
|
||||
-D OTHERNET_DC_REV=2206
|
||||
-I variants/dreamcatcher
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
|
||||
@@ -4,6 +4,7 @@ board_level = extra
|
||||
extends = esp32s3_base
|
||||
upload_protocol = esptool
|
||||
board = esp32-s3-pico
|
||||
board_build.partitions = default_16MB.csv
|
||||
|
||||
board_upload.use_1200bps_touch = yes
|
||||
board_upload.wait_for_upload_port = yes
|
||||
|
||||
12
variants/hackerboxes_esp32_io/platformio.ini
Normal file
12
variants/hackerboxes_esp32_io/platformio.ini
Normal file
@@ -0,0 +1,12 @@
|
||||
[env:hackerboxes-esp32-io]
|
||||
extends = esp32_base
|
||||
board = esp32dev
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-I variants/hackerboxes_esp32_io
|
||||
monitor_speed = 115200
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyUSB0
|
||||
upload_speed = 921600
|
||||
30
variants/hackerboxes_esp32_io/variant.h
Normal file
30
variants/hackerboxes_esp32_io/variant.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
// HACKBOX LoRa IO Kit
|
||||
// Uses a ESP-32-WROOM and a RA-01SH (SX1262) LoRa Board
|
||||
|
||||
#define LED_PIN 2 // LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
#define HAS_SCREEN 0
|
||||
#define HAS_GPS 0
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
|
||||
#define USE_SX1262
|
||||
#define LORA_SCK 18
|
||||
#define LORA_MISO 19
|
||||
#define LORA_MOSI 23
|
||||
#define LORA_CS 5
|
||||
#define LORA_DIO0 RADIOLIB_NC
|
||||
#define LORA_RESET 27
|
||||
#define LORA_DIO1 33
|
||||
#define LORA_DIO2 RADIOLIB_NC
|
||||
#define LORA_BUSY 32
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_BUSY
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_MAX_POWER 22 // Max power of the RA-01SH is 22db
|
||||
14
variants/hackerboxes_esp32c3_oled/platformio.ini
Normal file
14
variants/hackerboxes_esp32c3_oled/platformio.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
[env:hackerboxes-esp32c3-oled]
|
||||
extends = esp32c3_base
|
||||
board = esp32-c3-devkitm-1
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-I variants/hackerboxes_esp32c3_oled
|
||||
monitor_speed = 115200
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyUSB0
|
||||
upload_speed = 921600
|
||||
36
variants/hackerboxes_esp32c3_oled/variant.h
Normal file
36
variants/hackerboxes_esp32c3_oled/variant.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#define BUTTON_PIN 9
|
||||
|
||||
// Hackerboxes LoRa ESP32-C3 OLED Kit
|
||||
// Uses a ESP32-C3 OLED Board and a RA-01SH (SX1262) LoRa Board
|
||||
|
||||
#define LED_PIN 8 // LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
#define HAS_SCREEN 0
|
||||
#define HAS_GPS 0
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
|
||||
// #define USE_SSD1306_72_40
|
||||
// #define I2C_SDA 5 // I2C pins for this board
|
||||
// #define I2C_SCL 6 //
|
||||
// #define TFT_WIDTH 72
|
||||
// #define TFT_HEIGHT 40
|
||||
|
||||
#define USE_SX1262
|
||||
#define LORA_SCK 4
|
||||
#define LORA_MISO 7
|
||||
#define LORA_MOSI 3
|
||||
#define LORA_CS 1
|
||||
#define LORA_DIO0 RADIOLIB_NC
|
||||
#define LORA_RESET 0
|
||||
#define LORA_DIO1 20
|
||||
#define LORA_DIO2 RADIOLIB_NC
|
||||
#define LORA_BUSY 10
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_BUSY
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_MAX_POWER 22 // Max power of the RA-01SH is 22db
|
||||
@@ -2,7 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_check = true
|
||||
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -I variants/heltec_capsule_sensor_v3
|
||||
-D HELTEC_CAPSULE_SENSOR_V3
|
||||
|
||||
11
variants/heltec_sensor_hub/platformio.ini
Normal file
11
variants/heltec_sensor_hub/platformio.ini
Normal file
@@ -0,0 +1,11 @@
|
||||
[env:heltec_sensor_hub]
|
||||
extends = esp32s3_base
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_check = true
|
||||
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -I variants/heltec_sensor_hub
|
||||
-D HELTEC_SENSOR_HUB
|
||||
|
||||
lib_deps = ${esp32s3_base.lib_deps}
|
||||
adafruit/Adafruit NeoPixel @ ^1.12.0
|
||||
46
variants/heltec_sensor_hub/variant.h
Normal file
46
variants/heltec_sensor_hub/variant.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#define EXT_PWR_DETECT 20
|
||||
|
||||
#define BUTTON_PIN 17
|
||||
|
||||
#define BATTERY_PIN 7 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
#define ADC_CHANNEL ADC1_GPIO7_CHANNEL
|
||||
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
|
||||
#define ADC_MULTIPLIER (4.9 * 1.045)
|
||||
#define ADC_CTRL 34 // active HIGH, powers the voltage divider. Only on 1.1
|
||||
#define ADC_CTRL_ENABLED HIGH
|
||||
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||
#define NEOPIXEL_DATA 18 // gpio pin used to send data to the neopixels
|
||||
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use
|
||||
|
||||
#define USE_SX1262
|
||||
#define LORA_DIO0 RADIOLIB_NC
|
||||
#define LORA_RESET 12
|
||||
#define LORA_DIO1 14 // SX1262 IRQ
|
||||
#define LORA_DIO2 13 // SX1262 BUSY
|
||||
|
||||
#define LORA_SCK 9
|
||||
#define LORA_MISO 11
|
||||
#define LORA_MOSI 10
|
||||
#define LORA_CS 8
|
||||
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_DIO2
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
#define I2C_SDA 1
|
||||
#define I2C_SCL 2
|
||||
#define HAS_SCREEN 0
|
||||
#define SENSOR_POWER_CTRL_PIN 33
|
||||
#define SENSOR_POWER_ON 1
|
||||
|
||||
#define PERIPHERAL_WARMUP_MS 100
|
||||
|
||||
#define ESP32S3_WAKE_TYPE ESP_EXT1_WAKEUP_ANY_HIGH
|
||||
|
||||
#define ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE 1
|
||||
@@ -2,7 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_check = true
|
||||
# Temporary until espressif creates a release with this new target
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -D HELTEC_V3 -I variants/heltec_v3
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[env:heltec-vision-master-e213]
|
||||
extends = esp32s3_base
|
||||
board = heltec_vision_master_e213
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
${esp32s3_base.build_flags}
|
||||
-Ivariants/heltec_vision_master_e213
|
||||
-DHELTEC_VISION_MASTER_E213
|
||||
-DUSE_EINK
|
||||
@@ -22,6 +23,7 @@ upload_speed = 115200
|
||||
[env:heltec-vision-master-e213-inkhud]
|
||||
extends = esp32s3_base, inkhud
|
||||
board = heltec_vision_master_e213
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter}
|
||||
${inkhud.build_src_filter}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[env:heltec-vision-master-e290]
|
||||
extends = esp32s3_base
|
||||
board = heltec_vision_master_e290
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-I variants/heltec_vision_master_e290
|
||||
@@ -26,6 +27,7 @@ upload_speed = 115200
|
||||
[env:heltec-vision-master-e290-inkhud]
|
||||
extends = esp32s3_base, inkhud
|
||||
board = heltec_vision_master_e290
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter}
|
||||
${inkhud.build_src_filter}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[env:heltec-vision-master-t190]
|
||||
extends = esp32s3_base
|
||||
board = heltec_vision_master_t190
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-Ivariants/heltec_vision_master_t190
|
||||
-DHELTEC_VISION_MASTER_T190
|
||||
; -D PRIVATE_HW
|
||||
-DHELTEC_VISION_MASTER_T190
|
||||
lib_deps =
|
||||
${esp32s3_base.lib_deps}
|
||||
lewisxhe/PCF8563_Library@^1.0.1
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[env:heltec-wireless-paper]
|
||||
extends = esp32s3_base
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-I variants/heltec_wireless_paper
|
||||
@@ -23,6 +24,7 @@ upload_speed = 115200
|
||||
[env:heltec-wireless-paper-inkhud]
|
||||
extends = esp32s3_base, inkhud
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter}
|
||||
${inkhud.build_src_filter}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board_level = extra
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-I variants/heltec_wireless_paper_v1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[env:heltec-wireless-tracker]
|
||||
extends = esp32s3_base
|
||||
board = heltec_wireless_tracker
|
||||
board_build.partitions = default_8MB.csv
|
||||
upload_protocol = esptool
|
||||
|
||||
build_flags =
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board_level = extra
|
||||
board = heltec_wireless_tracker
|
||||
board_build.partitions = default_8MB.csv
|
||||
upload_protocol = esptool
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -I variants/heltec_wireless_tracker_V1_0
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
[env:heltec-wsl-v3]
|
||||
extends = esp32s3_base
|
||||
board = heltec_wifi_lora_32_V3
|
||||
board_build.partitions = default_8MB.csv
|
||||
# Temporary until espressif creates a release with this new target
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -D HELTEC_WSL_V3 -I variants/heltec_wsl_v3
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
|
||||
@@ -4,6 +4,7 @@ board = icarus
|
||||
board_level = extra
|
||||
board_check = true
|
||||
board_build.mcu = esp32s3
|
||||
board_build.partitions = default_8MB.csv
|
||||
upload_protocol = esptool
|
||||
upload_speed = 921600
|
||||
platform_packages = platformio/framework-arduinoespressif32@https://github.com/PowerFeather/powerfeather-meshtastic-arduino-lib/releases/download/2.0.16a/esp32-2.0.16.zip
|
||||
@@ -15,5 +16,4 @@ build_unflags =
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -D PRIVATE_HW -I variants/icarus
|
||||
-DBOARD_HAS_PSRAM
|
||||
|
||||
-DARDUINO_USB_MODE=0
|
||||
-DARDUINO_USB_MODE=0
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
extends = esp32s3_base
|
||||
board = m5stack-cores3
|
||||
board_check = true
|
||||
board_build.partitions = default_16MB.csv
|
||||
upload_protocol = esptool
|
||||
|
||||
build_flags = ${esp32_base.build_flags}
|
||||
|
||||
@@ -28,7 +28,6 @@ build_flags = ${esp32s3_base.build_flags}
|
||||
-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
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board = bpi_picow_esp32_s3
|
||||
board_check = true
|
||||
board_build.partitions = default_8MB.csv
|
||||
;OpenOCD flash method
|
||||
;upload_protocol = esp-builtin
|
||||
;Normal method
|
||||
@@ -22,7 +23,6 @@ build_src_filter =
|
||||
|
||||
[env:picomputer-s3-tft]
|
||||
extends = env:picomputer-s3
|
||||
board_build.partitions = default_8MB.csv ; just for test
|
||||
|
||||
build_flags =
|
||||
${env:picomputer-s3.build_flags}
|
||||
@@ -35,7 +35,6 @@ build_flags =
|
||||
-D INPUTDRIVER_MATRIX_TYPE=1
|
||||
-D USE_PIN_BUZZER=PIN_BUZZER
|
||||
-D USE_SX127x
|
||||
-D MAX_NUM_NODES=200
|
||||
-D HAS_SCREEN=0
|
||||
-D HAS_TFT=1
|
||||
-D RAM_SIZE=1024
|
||||
|
||||
@@ -27,6 +27,7 @@ build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunctio
|
||||
-D USE_X11=1
|
||||
-D HAS_TFT=1
|
||||
-D HAS_SCREEN=0
|
||||
-D LV_CACHE_DEF_SIZE=6291456
|
||||
-D LV_BUILD_TEST=0
|
||||
-D LV_USE_LIBINPUT=1
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
@@ -56,7 +57,7 @@ build_flags = ${native_base.build_flags} -O0 -fsanitize=address -lX11 -linput -l
|
||||
-D USE_X11=1
|
||||
-D HAS_TFT=1
|
||||
-D HAS_SCREEN=0
|
||||
; -D CALIBRATE_TOUCH=0
|
||||
-D LV_CACHE_DEF_SIZE=6291456
|
||||
-D LV_BUILD_TEST=0
|
||||
-D LV_USE_LOG=1
|
||||
-D LV_USE_SYSMON=1
|
||||
|
||||
@@ -1,36 +1,23 @@
|
||||
[env:rak3172]
|
||||
extends = stm32_base
|
||||
board = wiscore_rak3172
|
||||
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
|
||||
build_flags =
|
||||
${stm32_base.build_flags}
|
||||
-Ivariants/rak3172
|
||||
-DSERIAL_UART_INSTANCE=1
|
||||
-DPIN_SERIAL_RX=PB7
|
||||
-DPIN_SERIAL_TX=PB6
|
||||
-DHAL_DAC_MODULE_ONLY
|
||||
-DHAL_ADC_MODULE_DISABLED
|
||||
-DHAL_COMP_MODULE_DISABLED
|
||||
-DHAL_CRC_MODULE_DISABLED
|
||||
-DHAL_CRYP_MODULE_DISABLED
|
||||
-DHAL_GTZC_MODULE_DISABLED
|
||||
-DHAL_HSEM_MODULE_DISABLED
|
||||
-DHAL_I2C_MODULE_DISABLED
|
||||
-DHAL_I2S_MODULE_DISABLED
|
||||
-DHAL_IPCC_MODULE_DISABLED
|
||||
-DHAL_IRDA_MODULE_DISABLED
|
||||
-DHAL_IWDG_MODULE_DISABLED
|
||||
-DHAL_LPTIM_MODULE_DISABLED
|
||||
-DHAL_PKA_MODULE_DISABLED
|
||||
-DHAL_RNG_MODULE_DISABLED
|
||||
-DHAL_RTC_MODULE_DISABLED
|
||||
-DHAL_SMARTCARD_MODULE_DISABLED
|
||||
-DHAL_SMBUS_MODULE_DISABLED
|
||||
-DHAL_TIM_MODULE_DISABLED
|
||||
-DHAL_WWDG_MODULE_DISABLED
|
||||
-DHAL_EXTI_MODULE_DISABLED
|
||||
-DHAL_SAI_MODULE_DISABLED
|
||||
-DHAL_ICACHE_MODULE_DISABLED
|
||||
-DHAL_RNG_MODULE_ENABLED
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
upload_port = stlink
|
||||
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
|
||||
-DMESHTASTIC_EXCLUDE_I2C=1
|
||||
-DMESHTASTIC_EXCLUDE_WIFI=1
|
||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH=1
|
||||
-DMESHTASTIC_EXCLUDE_GPS=1
|
||||
-DMESHTASTIC_EXCLUDE_SCREEN=1
|
||||
-DMESHTASTIC_EXCLUDE_MQTT=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERMON=1
|
||||
;-DPIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
|
||||
;-DCFG_DEBUG
|
||||
upload_port = stlink
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
STM32WLE5 Core Module for LoRaWAN® RAK3372
|
||||
https://store.rakwireless.com/products/wisblock-core-module-rak3372
|
||||
*/
|
||||
|
||||
/*
|
||||
This variant is a work in progress.
|
||||
Do not expect a working Meshtastic device with this target.
|
||||
@@ -7,6 +12,8 @@ Do not expect a working Meshtastic device with this target.
|
||||
#define _VARIANT_RAK3172_
|
||||
|
||||
#define USE_STM32WLx
|
||||
#define MAX_NUM_NODES 10
|
||||
|
||||
#endif
|
||||
#define LED_PIN PA0 // Green LED
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,9 @@ build_flags = ${rp2350_base.build_flags}
|
||||
-DHAS_WIFI=1
|
||||
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m33"
|
||||
-fexceptions # for exception handling in MQTT
|
||||
-DHAS_UDP_MULTICAST=1
|
||||
build_src_filter = ${rp2350_base.build_src_filter} +<mesh/wifi/>
|
||||
lib_deps =
|
||||
${rp2350_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
debug_build_flags = ${rp2350_base.build_flags}, -g
|
||||
debug_build_flags = ${rp2350_base.build_flags}, -g
|
||||
|
||||
@@ -10,9 +10,10 @@ build_flags = ${rp2040_base.build_flags}
|
||||
-DHW_SPI1_DEVICE
|
||||
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
|
||||
-fexceptions # for exception handling in MQTT
|
||||
-DHAS_UDP_MULTICAST=1
|
||||
build_src_filter = ${rp2040_base.build_src_filter} +<mesh/wifi/>
|
||||
lib_deps =
|
||||
${rp2040_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
debug_build_flags = ${rp2040_base.build_flags}, -g
|
||||
debug_tool = cmsis-dap ; for e.g. Picotool
|
||||
debug_tool = cmsis-dap ; for e.g. Picotool
|
||||
|
||||
@@ -6,6 +6,7 @@ platform_packages =
|
||||
|
||||
board = seeed-sensecap-indicator
|
||||
board_check = true
|
||||
board_build.partitions = default_8MB.csv
|
||||
upload_protocol = esptool
|
||||
|
||||
build_flags = ${esp32_base.build_flags}
|
||||
@@ -32,7 +33,6 @@ lib_deps = ${esp32s3_base.lib_deps}
|
||||
extends = env:seeed-sensecap-indicator
|
||||
board_level = main
|
||||
upload_speed = 460800
|
||||
board_build.partitions = default_8MB.csv ; must be here for some reason, board.json is not enough !?
|
||||
|
||||
build_flags =
|
||||
${env:seeed-sensecap-indicator.build_flags}
|
||||
@@ -46,7 +46,6 @@ build_flags =
|
||||
-D INPUTDRIVER_BUTTON_TYPE=38
|
||||
-D HAS_TELEMETRY=0
|
||||
-D CONFIG_DISABLE_HAL_LOCKS=1
|
||||
-D MAX_NUM_NODES=250
|
||||
-D HAS_SCREEN=0
|
||||
-D HAS_TFT=1
|
||||
-D DISPLAY_SET_RESOLUTION
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board = seeed-xiao-s3
|
||||
board_check = true
|
||||
board_build.mcu = esp32s3
|
||||
board_build.partitions = default_8MB.csv
|
||||
upload_protocol = esptool
|
||||
upload_speed = 921600
|
||||
lib_deps =
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
extends = esp32s3_base
|
||||
board = station-g2
|
||||
board_check = true
|
||||
board_build.partitions = default_16MB.csv
|
||||
board_build.mcu = esp32s3
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyACM0
|
||||
@@ -13,6 +14,6 @@ build_unflags =
|
||||
-DARDUINO_USB_MODE=1
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -D STATION_G2 -I variants/station-g2
|
||||
-DBOARD_HAS_PSRAM
|
||||
-DBOARD_HAS_PSRAM
|
||||
-DSTATION_G2
|
||||
-DARDUINO_USB_MODE=0
|
||||
-DARDUINO_USB_MODE=0
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
extends = esp32s3_base
|
||||
board = t-deck
|
||||
board_check = true
|
||||
board_build.partitions = default_16MB.csv
|
||||
upload_protocol = esptool
|
||||
|
||||
build_flags = ${esp32s3_base.build_flags}
|
||||
@@ -20,7 +21,6 @@ lib_deps = ${esp32s3_base.lib_deps}
|
||||
|
||||
[env:t-deck-tft]
|
||||
extends = env:t-deck
|
||||
board_build.partitions = default_16MB.csv
|
||||
|
||||
build_flags =
|
||||
${env:t-deck.build_flags}
|
||||
@@ -38,12 +38,11 @@ build_flags =
|
||||
-D INPUTDRIVER_ENCODER_DOWN=15
|
||||
-D INPUTDRIVER_ENCODER_BTN=0
|
||||
-D INPUTDRIVER_BUTTON_TYPE=0
|
||||
-D MAX_NUM_NODES=250
|
||||
-D HAS_SDCARD
|
||||
-D HAS_SCREEN=0
|
||||
-D HAS_TFT=1
|
||||
-D USE_I2S_BUZZER
|
||||
-D RAM_SIZE=4096
|
||||
-D RAM_SIZE=5120
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_CONF_INCLUDE_SIMPLE
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||
@@ -67,6 +66,7 @@ build_flags =
|
||||
-D VIEW_320x240
|
||||
; -D USE_DOUBLE_BUFFER
|
||||
-D USE_PACKET_API
|
||||
-D MAP_FULL_REDRAW
|
||||
|
||||
lib_deps =
|
||||
${env:t-deck.lib_deps}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user