Compare commits
47
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d132bd3154 | ||
|
|
d2eb635b36 | ||
|
|
da50aab27d | ||
|
|
9f34ea4230 | ||
|
|
8dd5377676 | ||
|
|
6c0ef72d02 | ||
|
|
c2624c6140 | ||
|
|
1de3e292a8 | ||
|
|
64949156d6 | ||
|
|
1aab2d880d | ||
|
|
7550b16f91 | ||
|
|
5778a469cf | ||
|
|
2ca305d439 | ||
|
|
0a2e4c7e0f | ||
|
|
211af899bd | ||
|
|
d292217c34 | ||
|
|
7eb5582646 | ||
|
|
a01937d6a9 | ||
|
|
0bce1e937f | ||
|
|
94b343d3d8 | ||
|
|
8ef885a7ba | ||
|
|
957b568a2d | ||
|
|
f0a67c5cb0 | ||
|
|
4a73482162 | ||
|
|
aad1a27cbf | ||
|
|
2b5e2b985f | ||
|
|
1997cbce40 | ||
|
|
ff1f02d164 | ||
|
|
2e5f44db16 | ||
|
|
1d595beab7 | ||
|
|
f382718f16 | ||
|
|
76a79dd8ec | ||
|
|
da236599d6 | ||
|
|
39908bfbd2 | ||
|
|
bcceff6f4d | ||
|
|
273bcdc4db | ||
|
|
a4eb6b0b63 | ||
|
|
5fa9b05d70 | ||
|
|
cccb181335 | ||
|
|
b365c94981 | ||
|
|
0d08680104 | ||
|
|
51a5957cf4 | ||
|
|
2bd1faa7af | ||
|
|
4271481300 | ||
|
|
64f415dc0f | ||
|
|
1d1ca1053b | ||
|
|
9a94e8bd9f |
Vendored
+1
-2
@@ -10,6 +10,5 @@
|
||||
},
|
||||
"[powershell]": {
|
||||
"editor.defaultFormatter": "ms-vscode.powershell"
|
||||
},
|
||||
"idf.currentSetup": "C:/Espressif/frameworks/esp-idf-v5.3.1/"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/NebraHat
|
||||
# Use for 1 watt hat
|
||||
Meta:
|
||||
name: NebraHat 1W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Nebra SX1262 Pi Hat - 1W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
# CS: 8 # Newer version of MeshtasticD do not need this? If issues uncomment this line
|
||||
IRQ: 22
|
||||
Busy: 4
|
||||
Reset: 18
|
||||
RXen: 25
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -1,20 +0,0 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/NebraHat
|
||||
# Use for 2 watt hat
|
||||
Meta:
|
||||
name: NebraHat 2W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Nebra SX1262 Pi Hat - 2W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
SX126X_MAX_POWER: 8
|
||||
# CS: 8 # Newer version of MeshtasticD do not need this? If issues uncomment this line
|
||||
IRQ: 22
|
||||
Busy: 4
|
||||
Reset: 18
|
||||
RXen: 25
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -18,4 +18,4 @@ Lora:
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
# CS: 8
|
||||
# CS: 8
|
||||
@@ -18,4 +18,4 @@ Lora:
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: 7
|
||||
# CS: 7
|
||||
@@ -1,19 +0,0 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/ZebraHAT
|
||||
# Use for 1 watt hat
|
||||
Meta:
|
||||
name: ZebraHat 1W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Zebra SX1262 Pi Hat - 1W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
SX126X_MAX_POWER: 18
|
||||
CS: 24
|
||||
IRQ: 22
|
||||
Busy: 27
|
||||
Reset: 17
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -1,20 +0,0 @@
|
||||
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/ZebraHAT
|
||||
# Use for 2 watt hat
|
||||
Meta:
|
||||
name: ZebraHat 2W
|
||||
support: community
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262 # Zebra SX1262 Pi Hat - 2W
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
SX126X_MAX_POWER: 8
|
||||
CS: 24
|
||||
IRQ: 22
|
||||
Busy: 27
|
||||
Reset: 17
|
||||
RXen: 25
|
||||
I2C:
|
||||
I2CDevice: /dev/i2c-1
|
||||
@@ -29,8 +29,6 @@ Lora:
|
||||
- pin: 50 # GPIO1_C2 (physical 16)
|
||||
gpiochip: 1
|
||||
line: 18
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
|
||||
# pin: 7
|
||||
|
||||
@@ -29,8 +29,6 @@ Lora:
|
||||
- pin: 50 # GPIO1_C2 (physical 16)
|
||||
gpiochip: 1
|
||||
line: 18
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
|
||||
# pin: 7
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
# Station G3 + BQ35LORA900V1M Primary Slot
|
||||
# Board Doc: https://wiki.bqvoy.com/en/devkits/station-g3
|
||||
Meta:
|
||||
name: B&Q Station G3 + BQ35LORA900V1M Primary Slot
|
||||
support: official
|
||||
compatible:
|
||||
- luckfox-lyra-zero-w # Armbian
|
||||
|
||||
Lora:
|
||||
Module: sx1262
|
||||
IRQ: # GPIO0_A5 (physical 15)
|
||||
pin: 5
|
||||
gpiochip: 0
|
||||
line: 5
|
||||
Reset: # GPIO1_D1 (physical 36)
|
||||
pin: 57
|
||||
gpiochip: 1
|
||||
line: 25
|
||||
Busy: # GPIO0_B4 (physical 18)
|
||||
pin: 12
|
||||
gpiochip: 0
|
||||
line: 12
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
# CS: # GPIO0_B2 (physical 24)
|
||||
# pin: 10
|
||||
# gpiochip: 0
|
||||
# line: 10
|
||||
@@ -29,8 +29,6 @@ Lora:
|
||||
- pin: 13 # GPIO0_B5
|
||||
gpiochip: 0
|
||||
line: 13
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B1
|
||||
# pin: 9
|
||||
|
||||
@@ -29,8 +29,6 @@ Lora:
|
||||
- pin: 13 # GPIO0_B5
|
||||
gpiochip: 0
|
||||
line: 13
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B1
|
||||
# pin: 9
|
||||
|
||||
@@ -31,8 +31,6 @@ Lora:
|
||||
- pin: 103 # GPIO3_A7 (physical 16)
|
||||
gpiochip: 3
|
||||
line: 7
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
|
||||
# pin: 15
|
||||
|
||||
@@ -31,8 +31,6 @@ Lora:
|
||||
- pin: 103 # GPIO3_A7 (physical 16)
|
||||
gpiochip: 3
|
||||
line: 7
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.1
|
||||
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
|
||||
# pin: 15
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# Station G3 + BQ35LORA900V1M Primary Slot
|
||||
# Board Doc: https://wiki.bqvoy.com/en/devkits/station-g3
|
||||
Meta:
|
||||
name: B&Q Station G3 + BQ35LORA900V1M Primary Slot
|
||||
support: official
|
||||
compatible:
|
||||
- raspberry-pi
|
||||
|
||||
Lora:
|
||||
Module: sx1262
|
||||
IRQ: 22
|
||||
Reset: 16
|
||||
Busy: 24
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
#CS: 8
|
||||
@@ -1,5 +1,3 @@
|
||||
# This config works with all revisions of the Meshtoad USB radio.
|
||||
|
||||
Meta:
|
||||
name: meshtoad-e22
|
||||
support: official
|
||||
|
||||
+29
-25
@@ -219,37 +219,41 @@ with open(jsonLoc) as f:
|
||||
jsonStr = re.sub("//.*","", f.read(), flags=re.MULTILINE)
|
||||
userPrefs = json.loads(jsonStr)
|
||||
|
||||
pref_flags = []
|
||||
# Pre-process the userPrefs
|
||||
for pref in userPrefs:
|
||||
if userPrefs[pref].startswith("{"):
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref].lstrip("-").replace(".", "").isdigit():
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref] == "true" or userPrefs[pref] == "false":
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref].startswith("meshtastic_"):
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
# If the value is a string, we need to wrap it in quotes
|
||||
else:
|
||||
pref_flags.append("-D" + pref + "=" + env.StringifyMacro(userPrefs[pref]) + "")
|
||||
|
||||
# General options that are passed to the C and C++ compilers
|
||||
# Calculate unix epoch for current day (midnight)
|
||||
current_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
build_epoch = int(current_date.timestamp())
|
||||
|
||||
cpp_defines = [
|
||||
("APP_VERSION", verObj["long"]),
|
||||
("APP_VERSION_SHORT", verObj["short"]),
|
||||
("APP_ENV", env.get("PIOENV")),
|
||||
("APP_REPO", repo_owner),
|
||||
("BUILD_EPOCH", str(build_epoch)),
|
||||
]
|
||||
flags = [
|
||||
"-DAPP_VERSION=" + verObj["long"],
|
||||
"-DAPP_VERSION_SHORT=" + verObj["short"],
|
||||
"-DAPP_ENV=" + env.get("PIOENV"),
|
||||
"-DAPP_REPO=" + repo_owner,
|
||||
"-DBUILD_EPOCH=" + str(build_epoch),
|
||||
] + pref_flags
|
||||
|
||||
# Process userPrefs into CPPDEFINES
|
||||
for pref in userPrefs:
|
||||
val = userPrefs[pref]
|
||||
if val.startswith("{"):
|
||||
cpp_defines.append((pref, val))
|
||||
elif val.lstrip("-").replace(".", "").isdigit():
|
||||
cpp_defines.append((pref, val))
|
||||
elif val == "true" or val == "false":
|
||||
cpp_defines.append((pref, val))
|
||||
elif val.startswith("meshtastic_"):
|
||||
cpp_defines.append((pref, val))
|
||||
else:
|
||||
cpp_defines.append((pref, env.StringifyMacro(val)))
|
||||
print("Using flags:")
|
||||
for flag in flags:
|
||||
print(flag)
|
||||
|
||||
print("Using CPPDEFINES:")
|
||||
for d in cpp_defines:
|
||||
print(f" -D{d[0]}={d[1]}")
|
||||
|
||||
projenv.Append(CPPDEFINES=cpp_defines)
|
||||
projenv.Append(
|
||||
CCFLAGS=flags,
|
||||
)
|
||||
|
||||
for lb in env.GetLibBuilders():
|
||||
if lb.name == "meshtastic-device-ui":
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DLILYGO_TBEAM_BPF",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"psram_type": "opi",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "t-beam-bpf"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "LilyGo TBeam-BPF",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "http://www.lilygo.cn/",
|
||||
"vendor": "LilyGo"
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_T_IMPULSE_PLUS -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x8029"]],
|
||||
"usb_product": "T-Impulse-Plus-nRF52840",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "t-impulse-plus",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Lilygo T-Impulse-Plus-nRF52840",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"nrfutil",
|
||||
"stlink",
|
||||
"cmsis-dap",
|
||||
"blackmagic"
|
||||
]
|
||||
},
|
||||
"url": "https://www.lilygo.cc/",
|
||||
"vendor": "Lilygo"
|
||||
}
|
||||
Vendored
+1
-1
@@ -33,5 +33,5 @@ if [[ -n $GPG_KEY_ID ]]; then
|
||||
debuild -S -nc -k"$GPG_KEY_ID"
|
||||
else
|
||||
# Build the source deb without signing (forks)
|
||||
debuild -S -nc -us -uc
|
||||
debuild -S -nc
|
||||
fi
|
||||
|
||||
+1
-2
@@ -13,7 +13,7 @@ extra_configs =
|
||||
description = Meshtastic
|
||||
|
||||
[env]
|
||||
; test_build_src = true ; disabled for faster incremental builds
|
||||
test_build_src = true
|
||||
extra_scripts =
|
||||
pre:bin/platformio-pre.py
|
||||
bin/platformio-custom.py
|
||||
@@ -62,7 +62,6 @@ build_flags = -Wno-missing-field-initializers
|
||||
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
|
||||
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
|
||||
#-D OLED_PL=1
|
||||
#-D OLED_ZH=1 ; uncomment for compile-time Chinese font (runtime switching works without this on TFT)
|
||||
#-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs
|
||||
#-D DEBUG_LOOP_TIMING=1 ; uncomment to add main loop timing logs
|
||||
|
||||
|
||||
+31
-118
@@ -88,9 +88,6 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
@@ -122,93 +119,6 @@ bool fsFormat()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FSCom
|
||||
namespace
|
||||
{
|
||||
bool pathEndsWithDot(const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
size_t length = strlen(path);
|
||||
return length > 0 && path[length - 1] == '.';
|
||||
}
|
||||
|
||||
bool copyFilePath(char *dest, size_t destSize, const char *path, bool *wasLimited)
|
||||
{
|
||||
if (!path || destSize == 0) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlcpy(dest, path, destSize) >= destSize) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void collectFiles(const char *dirname, uint8_t levels, size_t maxCount, std::vector<meshtastic_FileInfo> &filenames,
|
||||
bool *wasLimited)
|
||||
{
|
||||
if (!dirname)
|
||||
return;
|
||||
|
||||
File root = FSCom.open(dirname, FILE_O_READ);
|
||||
if (!root)
|
||||
return;
|
||||
if (!root.isDirectory()) {
|
||||
root.close();
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
// file.name()[0] check is a workaround for a bug in the Adafruit LittleFS nrf52 glue (see issue 4395)
|
||||
while (file && file.name()[0]) {
|
||||
if (filenames.size() >= maxCount) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
file.close();
|
||||
break;
|
||||
}
|
||||
const char *fileName = file.name();
|
||||
if (file.isDirectory() && !pathEndsWithDot(fileName)) {
|
||||
char pathBuffer[sizeof(((meshtastic_FileInfo *)nullptr)->file_name)] = {};
|
||||
#ifdef ARCH_ESP32
|
||||
const char *subDirPath = file.path();
|
||||
#else
|
||||
const char *subDirPath = fileName;
|
||||
#endif
|
||||
bool hasSubDirPath = copyFilePath(pathBuffer, sizeof(pathBuffer), subDirPath, wasLimited);
|
||||
file.close();
|
||||
|
||||
if (levels && hasSubDirPath) {
|
||||
collectFiles(pathBuffer, levels - 1, maxCount, filenames, wasLimited);
|
||||
} else if (wasLimited) {
|
||||
*wasLimited = true;
|
||||
}
|
||||
} else {
|
||||
meshtastic_FileInfo fileInfo = {"", static_cast<uint32_t>(file.size())};
|
||||
#ifdef ARCH_ESP32
|
||||
bool hasFilePath = copyFilePath(fileInfo.file_name, sizeof(fileInfo.file_name), file.path(), wasLimited);
|
||||
#else
|
||||
bool hasFilePath = copyFilePath(fileInfo.file_name, sizeof(fileInfo.file_name), file.name(), wasLimited);
|
||||
#endif
|
||||
if (hasFilePath && !pathEndsWithDot(fileInfo.file_name)) {
|
||||
filenames.push_back(fileInfo);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
root.close();
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the list of files in a directory.
|
||||
*
|
||||
@@ -217,40 +127,43 @@ void collectFiles(const char *dirname, uint8_t levels, size_t maxCount, std::vec
|
||||
*
|
||||
* @param dirname The name of the directory.
|
||||
* @param levels The number of levels of subdirectories to list.
|
||||
* @param maxCount The maximum number of files to collect before truncating the walk.
|
||||
* @param wasLimited Optional out-param, set to true if the listing was truncated (by maxCount or low memory).
|
||||
* @return A vector of meshtastic_FileInfo for each file in the directory.
|
||||
* @return A vector of strings containing the full path of each file in the directory.
|
||||
*/
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels, size_t maxCount, bool *wasLimited)
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
|
||||
{
|
||||
std::vector<meshtastic_FileInfo> filenames = {};
|
||||
if (wasLimited)
|
||||
*wasLimited = false;
|
||||
#ifdef FSCom
|
||||
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
|
||||
size_t reservedCount = maxCount;
|
||||
while (reservedCount > 0) {
|
||||
try {
|
||||
filenames.reserve(reservedCount);
|
||||
break;
|
||||
} catch (const std::bad_alloc &) {
|
||||
reservedCount /= 2;
|
||||
} catch (const std::length_error &) {
|
||||
reservedCount /= 2;
|
||||
}
|
||||
}
|
||||
if (reservedCount == 0) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
File root = FSCom.open(dirname, FILE_O_READ);
|
||||
if (!root)
|
||||
return filenames;
|
||||
}
|
||||
if (reservedCount < maxCount) {
|
||||
if (wasLimited)
|
||||
*wasLimited = true;
|
||||
maxCount = reservedCount;
|
||||
}
|
||||
if (!root.isDirectory())
|
||||
return filenames;
|
||||
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
#ifdef ARCH_ESP32
|
||||
const char *filepath = file.path();
|
||||
#else
|
||||
const char *filepath = file.name();
|
||||
#endif
|
||||
collectFiles(dirname, levels, maxCount, filenames, wasLimited);
|
||||
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
if (levels) {
|
||||
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(filepath, levels - 1);
|
||||
filenames.insert(filenames.end(), subDirFilenames.begin(), subDirFilenames.end());
|
||||
file.close();
|
||||
}
|
||||
} else {
|
||||
meshtastic_FileInfo fileInfo = {"", static_cast<uint32_t>(file.size())};
|
||||
strncpy(fileInfo.file_name, filepath, sizeof(fileInfo.file_name) - 1);
|
||||
fileInfo.file_name[sizeof(fileInfo.file_name) - 1] = '\0';
|
||||
if (!String(fileInfo.file_name).endsWith(".")) {
|
||||
filenames.push_back(fileInfo);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
root.close();
|
||||
#endif
|
||||
return filenames;
|
||||
}
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ void fsListFiles();
|
||||
bool copyFile(const char *from, const char *to);
|
||||
bool renameFile(const char *pathFrom, const char *pathTo);
|
||||
bool fsFormat();
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels, size_t maxCount = 64, bool *wasLimited = nullptr);
|
||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
||||
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
||||
void rmDir(const char *dirname);
|
||||
void setupSDCard();
|
||||
+16
-15
@@ -24,7 +24,6 @@
|
||||
#include "main.h"
|
||||
#include "meshUtils.h"
|
||||
#include "power/PowerHAL.h"
|
||||
#include "power/SGM41562.h"
|
||||
#include "sleep.h"
|
||||
#ifdef ARCH_ESP32
|
||||
// #include <driver/adc.h>
|
||||
@@ -546,10 +545,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
// lastly provide a fallback to indicate external power when fully charged.
|
||||
virtual bool isVbusIn() override
|
||||
{
|
||||
#ifdef HAS_SGM41562
|
||||
if (sgm41562 && sgm41562->refresh())
|
||||
return sgm41562->isInputPowerGood();
|
||||
#endif
|
||||
#ifdef EXT_PWR_DETECT
|
||||
return digitalRead(EXT_PWR_DETECT) == EXT_PWR_DETECT_VALUE;
|
||||
|
||||
@@ -566,10 +561,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
/// we can't be smart enough to say 'full'?
|
||||
virtual bool isCharging() override
|
||||
{
|
||||
#ifdef HAS_SGM41562
|
||||
if (sgm41562 && sgm41562->refresh())
|
||||
return sgm41562->isCharging();
|
||||
#endif
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(HAS_PMU)
|
||||
if (hasRAK()) {
|
||||
return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse;
|
||||
@@ -776,12 +767,6 @@ bool Power::analogInit()
|
||||
*/
|
||||
bool Power::setup()
|
||||
{
|
||||
#ifdef HAS_SGM41562
|
||||
// Initialize the charger early so AnalogBatteryLevel can read charging
|
||||
// state from it. The charger does not provide battery voltage / percent —
|
||||
// those still come from the platform ADC via analogInit() below.
|
||||
initSGM41562(SGM41562_WIRE);
|
||||
#endif
|
||||
bool found = false;
|
||||
if (axpChipInit()) {
|
||||
found = true;
|
||||
@@ -1382,6 +1367,22 @@ bool Power::axpChipInit()
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
|
||||
PMU->disablePowerOutput(XPOWERS_VBACKUP);
|
||||
} else if (HW_VENDOR == meshtastic_HardwareModel_TBEAM_BPF) {
|
||||
// T-Beam BPF rail map (per schematic LilyGo_TBeam_BPF r2025-05-08):
|
||||
// DCDC1 -> ESP32 + OLED 3V3 (always on, protected)
|
||||
// ALDO2 -> MicroSD 3V3 (OFF at reset, must enable)
|
||||
// ALDO4 -> L76K GNSS 3V3 (OFF at reset, must enable)
|
||||
// ALDO1/3, BLDO1/2, DLDO1 -> user headers / unused at boot, leave at reset defaults.
|
||||
// LoRa power is outside the PMU (external P-MOSFET switched by RF95_POWER_EN / IO16).
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO4);
|
||||
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||
|
||||
// Make sure nothing's driving into an unused rail
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC5);
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO1);
|
||||
}
|
||||
|
||||
// disable all axp chip interrupt
|
||||
|
||||
+12
-87
@@ -31,63 +31,13 @@ static uint32_t
|
||||
timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
||||
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
||||
|
||||
#ifdef PIO_UNIT_TESTING
|
||||
// Test seam: unit tests can inject a fake system clock (e.g. the uptime seconds that
|
||||
// gettimeofday() returns on boards without a real RTC, like RP2040) and force readFromRTC()
|
||||
// down the no-hardware-RTC fallback even when a hardware-RTC branch is compiled in.
|
||||
static bool hasMockSystemTime = false;
|
||||
static bool forceSystemTimeFallback = false;
|
||||
static struct timeval mockSystemTime = {};
|
||||
#endif
|
||||
|
||||
// Reads the platform system clock (or the injected mock during unit tests). Used only by the
|
||||
// no-hardware-RTC fallback below, so it may be unused on builds with a hardware RTC.
|
||||
[[maybe_unused]] static bool readSystemTime(struct timeval *tv)
|
||||
{
|
||||
#ifdef PIO_UNIT_TESTING
|
||||
if (hasMockSystemTime) {
|
||||
*tv = mockSystemTime;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return gettimeofday(tv, NULL) == 0;
|
||||
}
|
||||
|
||||
// Seeds the clock from the system time on boards without a hardware RTC. gettimeofday() can
|
||||
// return uptime rather than wall-clock time there (e.g. RP2040), so only adopt it when we have
|
||||
// nothing better yet -- never clobber a higher-quality GPS/NTP/phone source (issue #9828).
|
||||
[[maybe_unused]] static RTCSetResult readFromSystemTimeFallback()
|
||||
{
|
||||
struct timeval tv;
|
||||
if (readSystemTime(&tv)) {
|
||||
uint32_t now = millis();
|
||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
LOG_DEBUG("Seed time from system clock: %lu", (unsigned long)printableEpoch);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
} else {
|
||||
LOG_DEBUG("Ignore system clock fallback (%lu); current RTC quality is %s", (unsigned long)printableEpoch,
|
||||
RtcName(currentQuality));
|
||||
}
|
||||
return RTCSetResultSuccess;
|
||||
}
|
||||
return RTCSetResultNotSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads date/time from the RTC module (or system-time fallback) and seeds internal timekeeping.
|
||||
* @return RTCSetResultSuccess if a time source was read successfully (even if an existing higher-quality time is retained).
|
||||
* Reads the current date and time from the RTC module and updates the system time.
|
||||
* @return True if the RTC was successfully read and the system time was updated, false otherwise.
|
||||
*/
|
||||
RTCSetResult readFromRTC()
|
||||
{
|
||||
#ifdef PIO_UNIT_TESTING
|
||||
if (forceSystemTimeFallback) {
|
||||
return readFromSystemTimeFallback();
|
||||
}
|
||||
#endif
|
||||
|
||||
[[maybe_unused]] struct timeval tv; /* btw settimeofday() is helpful here too*/
|
||||
struct timeval tv; /* btw settimeofday() is helpful here too*/
|
||||
#ifdef RV3028_RTC
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
uint32_t now = millis();
|
||||
@@ -212,7 +162,14 @@ RTCSetResult readFromRTC()
|
||||
}
|
||||
}
|
||||
#else
|
||||
return readFromSystemTimeFallback();
|
||||
if (!gettimeofday(&tv, NULL)) {
|
||||
uint32_t now = millis();
|
||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
LOG_DEBUG("Read RTC time as %ld", printableEpoch);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
return RTCSetResultSuccess;
|
||||
}
|
||||
#endif
|
||||
return RTCSetResultNotSet;
|
||||
}
|
||||
@@ -335,7 +292,7 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
|
||||
LOG_WARN("Failed to set time for RX8130CE");
|
||||
}
|
||||
}
|
||||
#elif defined(ARCH_ESP32) || defined(ARCH_RP2040)
|
||||
#elif defined(ARCH_ESP32)
|
||||
settimeofday(tv, NULL);
|
||||
#endif
|
||||
|
||||
@@ -466,38 +423,6 @@ void setBootRelativeTimeForUnitTest(uint32_t secondsSinceBoot)
|
||||
lastSetFromPhoneNtpOrGps = 0;
|
||||
lastTimeValidationWarning = 0;
|
||||
}
|
||||
|
||||
void clearRTCSystemTimeForTests()
|
||||
{
|
||||
hasMockSystemTime = false;
|
||||
mockSystemTime = {};
|
||||
}
|
||||
|
||||
void setRTCSystemTimeForTests(const struct timeval *tv)
|
||||
{
|
||||
if (tv == NULL) {
|
||||
clearRTCSystemTimeForTests();
|
||||
return;
|
||||
}
|
||||
mockSystemTime = *tv;
|
||||
hasMockSystemTime = true;
|
||||
}
|
||||
|
||||
void setReadFromRTCUseSystemTimeForTests(bool enabled)
|
||||
{
|
||||
forceSystemTimeFallback = enabled;
|
||||
}
|
||||
|
||||
void resetRTCStateForTests()
|
||||
{
|
||||
currentQuality = RTCQualityNone;
|
||||
timeStartMsec = 0;
|
||||
zeroOffsetSecs = 0;
|
||||
lastSetFromPhoneNtpOrGps = 0;
|
||||
lastTimeValidationWarning = 0;
|
||||
setReadFromRTCUseSystemTimeForTests(false);
|
||||
clearRTCSystemTimeForTests();
|
||||
}
|
||||
#endif
|
||||
|
||||
time_t gm_mktime(const struct tm *tm)
|
||||
|
||||
@@ -56,10 +56,6 @@ RTCSetResult readFromRTC();
|
||||
|
||||
#ifdef PIO_UNIT_TESTING
|
||||
void setBootRelativeTimeForUnitTest(uint32_t secondsSinceBoot);
|
||||
void resetRTCStateForTests();
|
||||
void setRTCSystemTimeForTests(const struct timeval *tv);
|
||||
void clearRTCSystemTimeForTests();
|
||||
void setReadFromRTCUseSystemTimeForTests(bool enabled);
|
||||
#endif
|
||||
|
||||
time_t gm_mktime(const struct tm *tm);
|
||||
|
||||
+5
-286
@@ -39,7 +39,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "draw/NodeListRenderer.h"
|
||||
#include "draw/NotificationRenderer.h"
|
||||
#include "draw/UIRenderer.h"
|
||||
#include "graphics/fonts/OLEDDisplayFontsZH.h"
|
||||
#include "graphics/TFTColorRegions.h"
|
||||
#include "modules/CannedMessageModule.h"
|
||||
#include "security/LockdownDisplay.h"
|
||||
@@ -61,7 +60,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "graphics/TFTPalette.h"
|
||||
#include "graphics/emotes.h"
|
||||
#include "graphics/images.h"
|
||||
#include "graphics/l10n/Strings.h"
|
||||
#include "input/TouchScreenImpl1.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
@@ -142,11 +140,10 @@ static void drawLockdownLockScreenIntoBuffer(OLEDDisplay *display)
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_LARGE);
|
||||
display->drawString(w / 2, h / 2 - FONT_HEIGHT_LARGE, meshtastic::l10n::getString(meshtastic::l10n::StringKey::LOCKED));
|
||||
display->drawString(w / 2, h / 2 - FONT_HEIGHT_LARGE, "LOCKED");
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
char status[32];
|
||||
strncpy(status, meshtastic::l10n::getString(meshtastic::l10n::StringKey::ConnectToUnlock), 31);
|
||||
char status[32] = "Connect to unlock";
|
||||
if (powerStatus && powerStatus->getHasBattery()) {
|
||||
int pct = powerStatus->getBatteryChargePercent();
|
||||
snprintf(status, sizeof(status), "Battery %d%%", pct);
|
||||
@@ -734,10 +731,7 @@ void Screen::setup()
|
||||
// Enable display rendering
|
||||
useDisplay = true;
|
||||
|
||||
// Set the runtime display language from persisted config
|
||||
meshtastic::l10n::currentDisplayLanguage = uiconfig.language;
|
||||
|
||||
// Load brightness from UI config
|
||||
// Load saved brightness from UI config
|
||||
// For OLED displays (SSD1306), default brightness is 255 if not set
|
||||
if (uiconfig.screen_brightness == 0) {
|
||||
#if defined(USE_OLED) || defined(USE_SSD1306) || defined(USE_SH1106) || defined(USE_SH1107)
|
||||
@@ -825,9 +819,6 @@ void Screen::setup()
|
||||
// Enable UTF-8 to display mapping
|
||||
dispdev->setFontTableLookupFunction(customFontTableLookup);
|
||||
|
||||
// Load CJK (Chinese) font if language requires it
|
||||
loadCJKFontIfNeeded();
|
||||
|
||||
#ifdef USERPREFS_OEM_TEXT
|
||||
logo_timeout *= 2; // Give more time for branded boot logos
|
||||
#endif
|
||||
@@ -837,7 +828,7 @@ void Screen::setup()
|
||||
alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
|
||||
#ifdef ARCH_ESP32
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1)
|
||||
graphics::UIRenderer::drawFrameText(display, state, x, y, meshtastic::l10n::getString(meshtastic::l10n::StringKey::Resuming));
|
||||
graphics::UIRenderer::drawFrameText(display, state, x, y, "Resuming...");
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@@ -994,13 +985,6 @@ int32_t Screen::runOnce()
|
||||
return RUN_SAME;
|
||||
}
|
||||
|
||||
// Detect language changes from remote config (phone app)
|
||||
if (uiconfig.language != meshtastic::l10n::currentDisplayLanguage) {
|
||||
meshtastic::l10n::currentDisplayLanguage = uiconfig.language;
|
||||
loadCJKFontIfNeeded();
|
||||
setFrames(FOCUS_PRESERVE);
|
||||
}
|
||||
|
||||
if (displayHeight == 0) {
|
||||
displayHeight = dispdev->getHeight();
|
||||
}
|
||||
@@ -1068,7 +1052,7 @@ int32_t Screen::runOnce()
|
||||
}
|
||||
#endif
|
||||
if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0 && !suppressRebootBanner) {
|
||||
showSimpleBanner(meshtastic::l10n::getString(meshtastic::l10n::StringKey::Rebooting), 0);
|
||||
showSimpleBanner("Rebooting...", 0);
|
||||
}
|
||||
|
||||
// Process incoming commands.
|
||||
@@ -2226,271 +2210,6 @@ bool Screen::isOverlayBannerShowing()
|
||||
return NotificationRenderer::isOverlayBannerShowing();
|
||||
}
|
||||
|
||||
char Screen::customFontTableLookup(const uint8_t ch)
|
||||
{
|
||||
static uint8_t LASTCHAR;
|
||||
static bool SKIPREST;
|
||||
static int8_t cjkRemaining = 0;
|
||||
|
||||
if (cjkRemaining > 0) {
|
||||
cjkRemaining--;
|
||||
LASTCHAR = ch;
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
if (ch < 128) {
|
||||
LASTCHAR = 0;
|
||||
SKIPREST = false;
|
||||
cjkRemaining = 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
uint8_t last = LASTCHAR;
|
||||
LASTCHAR = ch;
|
||||
|
||||
switch (last) {
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == 0xC2 || ch == 0xC3)
|
||||
return (uint8_t)0;
|
||||
|
||||
#if defined(OLED_PL)
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
if (ch == 147)
|
||||
return (uint8_t)(ch);
|
||||
else if (ch == 179)
|
||||
return (uint8_t)(148);
|
||||
else
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
break;
|
||||
}
|
||||
case 0xC4: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch);
|
||||
}
|
||||
case 0xC5: {
|
||||
SKIPREST = false;
|
||||
if (ch == 132)
|
||||
return (uint8_t)(136);
|
||||
else if (ch == 186)
|
||||
return (uint8_t)(137);
|
||||
else
|
||||
return (uint8_t)(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
|
||||
return (uint8_t)0;
|
||||
#endif
|
||||
|
||||
#if defined(OLED_UA) || defined(OLED_RU)
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
case 0xD0: {
|
||||
SKIPREST = false;
|
||||
if (ch == 132)
|
||||
return (uint8_t)(170);
|
||||
if (ch == 134)
|
||||
return (uint8_t)(178);
|
||||
if (ch == 135)
|
||||
return (uint8_t)(175);
|
||||
if (ch == 129)
|
||||
return (uint8_t)(168);
|
||||
if (ch > 143 && ch < 192)
|
||||
return (uint8_t)(ch + 48);
|
||||
break;
|
||||
}
|
||||
case 0xD1: {
|
||||
SKIPREST = false;
|
||||
if (ch == 148)
|
||||
return (uint8_t)(186);
|
||||
if (ch == 150)
|
||||
return (uint8_t)(179);
|
||||
if (ch == 151)
|
||||
return (uint8_t)(191);
|
||||
if (ch == 145)
|
||||
return (uint8_t)(184);
|
||||
if (ch > 127 && ch < 144)
|
||||
return (uint8_t)(ch + 112);
|
||||
break;
|
||||
}
|
||||
case 0xD2: {
|
||||
SKIPREST = false;
|
||||
if (ch == 144)
|
||||
return (uint8_t)(165);
|
||||
if (ch == 145)
|
||||
return (uint8_t)(180);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82 || ch == 0xD0 || ch == 0xD1)
|
||||
return (uint8_t)0;
|
||||
#endif
|
||||
|
||||
#if defined(OLED_CS)
|
||||
switch (last) {
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
case 0xC4: {
|
||||
SKIPREST = false;
|
||||
if (ch == 140)
|
||||
return (uint8_t)(129);
|
||||
if (ch == 141)
|
||||
return (uint8_t)(138);
|
||||
if (ch == 142)
|
||||
return (uint8_t)(130);
|
||||
if (ch == 143)
|
||||
return (uint8_t)(139);
|
||||
if (ch == 154)
|
||||
return (uint8_t)(131);
|
||||
if (ch == 155)
|
||||
return (uint8_t)(140);
|
||||
if (ch == 185)
|
||||
return (uint8_t)(147);
|
||||
if (ch == 186)
|
||||
return (uint8_t)(148);
|
||||
if (ch == 189)
|
||||
return (uint8_t)(149);
|
||||
if (ch == 190)
|
||||
return (uint8_t)(150);
|
||||
break;
|
||||
}
|
||||
case 0xC5: {
|
||||
SKIPREST = false;
|
||||
if (ch == 135)
|
||||
return (uint8_t)(132);
|
||||
if (ch == 136)
|
||||
return (uint8_t)(141);
|
||||
if (ch == 152)
|
||||
return (uint8_t)(133);
|
||||
if (ch == 153)
|
||||
return (uint8_t)(142);
|
||||
if (ch == 160)
|
||||
return (uint8_t)(134);
|
||||
if (ch == 161)
|
||||
return (uint8_t)(143);
|
||||
if (ch == 164)
|
||||
return (uint8_t)(135);
|
||||
if (ch == 165)
|
||||
return (uint8_t)(144);
|
||||
if (ch == 174)
|
||||
return (uint8_t)(136);
|
||||
if (ch == 175)
|
||||
return (uint8_t)(145);
|
||||
if (ch == 189)
|
||||
return (uint8_t)(137);
|
||||
if (ch == 190)
|
||||
return (uint8_t)(146);
|
||||
if (ch == 148)
|
||||
return (uint8_t)(151);
|
||||
if (ch == 149)
|
||||
return (uint8_t)(152);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
|
||||
return (uint8_t)0;
|
||||
#endif
|
||||
|
||||
#if defined(OLED_GR)
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
case 0xCE: {
|
||||
SKIPREST = false;
|
||||
if (ch >= 145 && ch <= 161)
|
||||
return (uint8_t)(ch + 48);
|
||||
else if (ch >= 163 && ch <= 169)
|
||||
return (uint8_t)(ch + 48);
|
||||
else if (ch >= 177 && ch <= 193)
|
||||
return (uint8_t)(ch + 48);
|
||||
break;
|
||||
}
|
||||
case 0xCF: {
|
||||
SKIPREST = false;
|
||||
if (ch >= 130 && ch <= 137)
|
||||
return (uint8_t)(ch + 112);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xCE || ch == 0xCF)
|
||||
return (uint8_t)0;
|
||||
#endif
|
||||
|
||||
if (ch >= 0xE2 && ch <= 0xEF) {
|
||||
cjkRemaining = 2;
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
if (SKIPREST)
|
||||
return (uint8_t)0;
|
||||
SKIPREST = true;
|
||||
|
||||
return (uint8_t)191;
|
||||
}
|
||||
|
||||
void Screen::drawTextL10n(int16_t x, int16_t y, const char *text, OLEDDISPLAY_TEXT_ALIGNMENT alignment)
|
||||
{
|
||||
if (!dispdev || !text)
|
||||
return;
|
||||
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
|
||||
defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(RAK14014)
|
||||
if (meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_SIMPLIFIED_CHINESE ||
|
||||
meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_TRADITIONAL_CHINESE) {
|
||||
TFTDisplay *tftDisp = static_cast<TFTDisplay *>(dispdev);
|
||||
if (tftDisp->hasCJKFont()) {
|
||||
tftDisp->drawStringCJK(x, y, text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dispdev->setTextAlignment(alignment);
|
||||
dispdev->drawString(x, y, text);
|
||||
}
|
||||
|
||||
void Screen::setFontL10n(const uint8_t *fontData)
|
||||
{
|
||||
if (!dispdev)
|
||||
return;
|
||||
dispdev->setFont(fontData);
|
||||
}
|
||||
|
||||
void Screen::loadCJKFontIfNeeded()
|
||||
{
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
|
||||
defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(RAK14014)
|
||||
if (meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_SIMPLIFIED_CHINESE ||
|
||||
meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_TRADITIONAL_CHINESE) {
|
||||
TFTDisplay *tftDisp = static_cast<TFTDisplay *>(dispdev);
|
||||
if (!tftDisp->hasCJKFont()) {
|
||||
tftDisp->loadCJKFont(FontZH_CN_16, FontZH_CN_16_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
|
||||
#else
|
||||
|
||||
+247
-5
@@ -366,13 +366,255 @@ class Screen : public concurrency::OSThread
|
||||
enqueueCmd(ScreenCmd{.cmd = Cmd::NOOP});
|
||||
}
|
||||
|
||||
static char customFontTableLookup(const uint8_t ch);
|
||||
/// Overrides the default utf8 character conversion, to replace empty space with question marks
|
||||
static char customFontTableLookup(const uint8_t ch)
|
||||
{
|
||||
// UTF-8 to font table index converter
|
||||
// Code from http://playground.arduino.cc/Main/Utf8ascii
|
||||
static uint8_t LASTCHAR;
|
||||
static bool SKIPREST; // Only display a single unconvertable-character symbol per sequence of unconvertable characters
|
||||
|
||||
void drawTextL10n(int16_t x, int16_t y, const char *text, OLEDDISPLAY_TEXT_ALIGNMENT alignment = TEXT_ALIGN_LEFT);
|
||||
void setFontL10n(const uint8_t *fontData);
|
||||
if (ch < 128) { // Standard ASCII-set 0..0x7F handling
|
||||
LASTCHAR = 0;
|
||||
SKIPREST = false;
|
||||
return ch;
|
||||
}
|
||||
|
||||
// Load CJK font if language requires it (called from setup & on language change)
|
||||
void loadCJKFontIfNeeded();
|
||||
uint8_t last = LASTCHAR; // get last char
|
||||
LASTCHAR = ch;
|
||||
|
||||
switch (last) {
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2 || ch == 0xC3)
|
||||
return (uint8_t)0;
|
||||
|
||||
#if defined(OLED_PL)
|
||||
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
|
||||
if (ch == 147)
|
||||
return (uint8_t)(ch); // Ó
|
||||
else if (ch == 179)
|
||||
return (uint8_t)(148); // ó
|
||||
else
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xC4: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch);
|
||||
}
|
||||
|
||||
case 0xC5: {
|
||||
SKIPREST = false;
|
||||
if (ch == 132)
|
||||
return (uint8_t)(136); // ń
|
||||
else if (ch == 186)
|
||||
return (uint8_t)(137); // ź
|
||||
else
|
||||
return (uint8_t)(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OLED_UA) || defined(OLED_RU)
|
||||
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
// map UTF-8 cyrillic chars to it Windows-1251 (CP-1251) ASCII codes
|
||||
// note: in this case we must use compatible font - provided ArialMT_Plain_10/16/24 by 'ThingPulse/esp8266-oled-ssd1306'
|
||||
// library have empty chars for non-latin ASCII symbols
|
||||
case 0xD0: {
|
||||
SKIPREST = false;
|
||||
if (ch == 132)
|
||||
return (uint8_t)(170); // Є
|
||||
if (ch == 134)
|
||||
return (uint8_t)(178); // І
|
||||
if (ch == 135)
|
||||
return (uint8_t)(175); // Ї
|
||||
if (ch == 129)
|
||||
return (uint8_t)(168); // Ё
|
||||
if (ch > 143 && ch < 192)
|
||||
return (uint8_t)(ch + 48);
|
||||
break;
|
||||
}
|
||||
case 0xD1: {
|
||||
SKIPREST = false;
|
||||
if (ch == 148)
|
||||
return (uint8_t)(186); // є
|
||||
if (ch == 150)
|
||||
return (uint8_t)(179); // і
|
||||
if (ch == 151)
|
||||
return (uint8_t)(191); // ї
|
||||
if (ch == 145)
|
||||
return (uint8_t)(184); // ё
|
||||
if (ch > 127 && ch < 144)
|
||||
return (uint8_t)(ch + 112);
|
||||
break;
|
||||
}
|
||||
case 0xD2: {
|
||||
SKIPREST = false;
|
||||
if (ch == 144)
|
||||
return (uint8_t)(165); // Ґ
|
||||
if (ch == 145)
|
||||
return (uint8_t)(180); // ґ
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82 || ch == 0xD0 || ch == 0xD1)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OLED_CS)
|
||||
|
||||
switch (last) {
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
|
||||
case 0xC4: {
|
||||
SKIPREST = false;
|
||||
if (ch == 140)
|
||||
return (uint8_t)(129); // Č
|
||||
if (ch == 141)
|
||||
return (uint8_t)(138); // č
|
||||
if (ch == 142)
|
||||
return (uint8_t)(130); // Ď
|
||||
if (ch == 143)
|
||||
return (uint8_t)(139); // ď
|
||||
if (ch == 154)
|
||||
return (uint8_t)(131); // Ě
|
||||
if (ch == 155)
|
||||
return (uint8_t)(140); // ě
|
||||
// Slovak specific glyphs
|
||||
if (ch == 185)
|
||||
return (uint8_t)(147); // Ĺ
|
||||
if (ch == 186)
|
||||
return (uint8_t)(148); // ĺ
|
||||
if (ch == 189)
|
||||
return (uint8_t)(149); // Ľ
|
||||
if (ch == 190)
|
||||
return (uint8_t)(150); // ľ
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xC5: {
|
||||
SKIPREST = false;
|
||||
if (ch == 135)
|
||||
return (uint8_t)(132); // Ň
|
||||
if (ch == 136)
|
||||
return (uint8_t)(141); // ň
|
||||
if (ch == 152)
|
||||
return (uint8_t)(133); // Ř
|
||||
if (ch == 153)
|
||||
return (uint8_t)(142); // ř
|
||||
if (ch == 160)
|
||||
return (uint8_t)(134); // Š
|
||||
if (ch == 161)
|
||||
return (uint8_t)(143); // š
|
||||
if (ch == 164)
|
||||
return (uint8_t)(135); // Ť
|
||||
if (ch == 165)
|
||||
return (uint8_t)(144); // ť
|
||||
if (ch == 174)
|
||||
return (uint8_t)(136); // Ů
|
||||
if (ch == 175)
|
||||
return (uint8_t)(145); // ů
|
||||
if (ch == 189)
|
||||
return (uint8_t)(137); // Ž
|
||||
if (ch == 190)
|
||||
return (uint8_t)(146); // ž
|
||||
// Slovak specific glyphs
|
||||
if (ch == 148)
|
||||
return (uint8_t)(151); // Ŕ
|
||||
if (ch == 149)
|
||||
return (uint8_t)(152); // ŕ
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OLED_GR)
|
||||
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
// Map UTF-8 Greek chars to Windows-1253 (CP-1253) ASCII codes
|
||||
case 0xCE: {
|
||||
SKIPREST = false;
|
||||
// Uppercase Greek: Α-Ρ (U+0391-U+03A1) -> CP-1253 193-209
|
||||
if (ch >= 145 && ch <= 161)
|
||||
return (uint8_t)(ch + 48);
|
||||
// Uppercase Greek: Σ-Ω (U+03A3-U+03A9) -> CP-1253 211-217
|
||||
else if (ch >= 163 && ch <= 169)
|
||||
return (uint8_t)(ch + 48);
|
||||
// Lowercase Greek: α-ρ (U+03B1-U+03C1) -> CP-1253 225-241
|
||||
else if (ch >= 177 && ch <= 193)
|
||||
return (uint8_t)(ch + 48);
|
||||
break;
|
||||
}
|
||||
case 0xCF: {
|
||||
SKIPREST = false;
|
||||
// Lowercase Greek: ς-ω (U+03C2-U+03C9) -> CP-1253 242-249
|
||||
if (ch >= 130 && ch <= 137)
|
||||
return (uint8_t)(ch + 112);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte Greek char formats
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xCE || ch == 0xCF)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
|
||||
// rest of it
|
||||
if (SKIPREST)
|
||||
return (uint8_t)0;
|
||||
SKIPREST = true;
|
||||
|
||||
return (uint8_t)191; // otherwise: return ¿ if character can't be converted (note that the font map we're using doesn't
|
||||
// stick to standard EASCII codes)
|
||||
}
|
||||
|
||||
/// Returns a handle to the DebugInfo screen.
|
||||
//
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
#include "graphics/fonts/OLEDDisplayFontsGR.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_ZH
|
||||
#include "graphics/fonts/OLEDDisplayFontsZH.h"
|
||||
#endif
|
||||
|
||||
#if (defined(CROWPANEL_ESP32S3_5_EPAPER) || defined(T5_S3_EPAPER_PRO)) && defined(USE_EINK)
|
||||
#include "graphics/fonts/EinkDisplayFonts.h"
|
||||
#endif
|
||||
|
||||
@@ -1636,35 +1636,4 @@ bool TFTDisplay::connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TFTDisplay::loadCJKFont(const uint8_t *vlwData, uint32_t vlwDataLen)
|
||||
{
|
||||
if (!tft || !vlwData || vlwDataLen == 0)
|
||||
return false;
|
||||
cjkFontLoaded = tft->loadFont(vlwData);
|
||||
if (cjkFontLoaded) {
|
||||
LOG_INFO("CJK font loaded (%u bytes)", vlwDataLen);
|
||||
} else {
|
||||
LOG_WARN("Failed to load CJK font");
|
||||
}
|
||||
return cjkFontLoaded;
|
||||
}
|
||||
|
||||
void TFTDisplay::drawStringCJK(int16_t x, int16_t y, const char *text)
|
||||
{
|
||||
if (!tft || !text || !cjkFontLoaded)
|
||||
return;
|
||||
concurrency::LockGuard g(spiLock);
|
||||
uint16_t fgColor = getThemeDefaultOnColor();
|
||||
tft->setTextColor(fgColor, getThemeDefaultOffColor());
|
||||
tft->setCursor(x, y);
|
||||
tft->print(text);
|
||||
}
|
||||
|
||||
int16_t TFTDisplay::getStringWidthCJK(const char *text)
|
||||
{
|
||||
if (!tft || !text || !cjkFontLoaded)
|
||||
return 0;
|
||||
return tft->textWidth(text);
|
||||
}
|
||||
|
||||
#endif // USE_TFTDISPLAY
|
||||
|
||||
@@ -38,12 +38,6 @@ class TFTDisplay : public OLEDDisplay
|
||||
// Functions for changing display brightness
|
||||
void setDisplayBrightness(uint8_t);
|
||||
|
||||
// CJK (Chinese/Japanese/Korean) text rendering via LovyanGFX
|
||||
bool loadCJKFont(const uint8_t *vlwData, uint32_t vlwDataLen);
|
||||
void drawStringCJK(int16_t x, int16_t y, const char *text);
|
||||
int16_t getStringWidthCJK(const char *text);
|
||||
bool hasCJKFont() const { return cjkFontLoaded; }
|
||||
|
||||
/**
|
||||
* shim to make the abstraction happy
|
||||
*
|
||||
@@ -70,5 +64,4 @@ class TFTDisplay : public OLEDDisplay
|
||||
|
||||
uint16_t *linePixelBuffer = nullptr;
|
||||
uint16_t *repaintChunkBuffer = nullptr;
|
||||
bool cjkFontLoaded = false;
|
||||
};
|
||||
|
||||
+143
-288
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,6 @@ class menuHandler
|
||||
DisplayUnits,
|
||||
MessageBubblesMenu,
|
||||
ThemeMenu,
|
||||
LanguagePicker,
|
||||
HamModeConfirm,
|
||||
LicensedToNormalConfirm
|
||||
};
|
||||
@@ -108,7 +107,6 @@ class menuHandler
|
||||
static void wifiBaseMenu();
|
||||
static void wifiToggleMenu();
|
||||
static void screenOptionsMenu();
|
||||
static void languagePickerMenu();
|
||||
static void powerMenu();
|
||||
static void nodeNameLengthMenu();
|
||||
static void frameTogglesMenu();
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "graphics/SharedUIDisplay.h"
|
||||
#include "graphics/TFTColorRegions.h"
|
||||
#include "graphics/TFTPalette.h"
|
||||
#include "graphics/l10n/Strings.h"
|
||||
#include "graphics/TimeFormatters.h"
|
||||
#include "graphics/emotes.h"
|
||||
#include "main.h"
|
||||
@@ -76,15 +75,6 @@ void scrollDown()
|
||||
|
||||
void drawStringWithEmotes(OLEDDisplay *display, int x, int y, const std::string &line, const Emote *emotes, int emoteCount)
|
||||
{
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
|
||||
defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(RAK14014) || defined(USE_ST7789) || \
|
||||
defined(USE_ST7796)
|
||||
if (meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_SIMPLIFIED_CHINESE ||
|
||||
meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_TRADITIONAL_CHINESE) {
|
||||
screen->drawTextL10n(x, y, line.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
graphics::EmoteRenderer::drawStringWithEmotes(display, x, y, line, FONT_HEIGHT_SMALL, emotes, emoteCount);
|
||||
}
|
||||
|
||||
@@ -492,7 +482,7 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// Still in ALL mode and no messages at all → show placeholder
|
||||
graphics::drawCommonHeader(display, x, y, titleStr);
|
||||
didReset = false;
|
||||
const char *messageString = meshtastic::l10n::getString(meshtastic::l10n::StringKey::NoMessages);
|
||||
const char *messageString = "No messages";
|
||||
int center_text = (SCREEN_WIDTH / 2) - (display->getStringWidth(messageString) / 2);
|
||||
display->drawString(center_text, getTextPositions(display)[2], messageString);
|
||||
graphics::drawCommonFooter(display, x, y);
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "graphics/TFTColorRegions.h"
|
||||
#include "graphics/TFTPalette.h"
|
||||
#include "graphics/images.h"
|
||||
#include "graphics/l10n/Strings.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "input/RotaryEncoderInterruptImpl1.h"
|
||||
#include "input/UpDownInterruptImpl1.h"
|
||||
#if HAS_BUTTON
|
||||
@@ -41,27 +39,6 @@ extern std::vector<std::string> functionSymbol;
|
||||
extern std::string functionSymbolString;
|
||||
extern bool hasUnreadMessage;
|
||||
|
||||
namespace
|
||||
{
|
||||
inline bool isCJKLanguage()
|
||||
{
|
||||
return meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_SIMPLIFIED_CHINESE ||
|
||||
meshtastic::l10n::currentDisplayLanguage == meshtastic_Language_TRADITIONAL_CHINESE;
|
||||
}
|
||||
|
||||
inline void drawBannerText(OLEDDisplay *display, int16_t x, int16_t y, const char *text)
|
||||
{
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
|
||||
defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(RAK14014)
|
||||
if (isCJKLanguage() && ::screen) {
|
||||
::screen->drawTextL10n(x, y, text);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
display->drawString(x, y, text);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
int bannerSignalBars = -1;
|
||||
@@ -207,7 +184,7 @@ void NotificationRenderer::drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
{
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(64 + x, y, meshtastic::l10n::getString(meshtastic::l10n::StringKey::CreatingSSLCert));
|
||||
display->drawString(64 + x, y, "Creating SSL certificate");
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
yield();
|
||||
@@ -216,9 +193,9 @@ void NotificationRenderer::drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
if ((millis() / 1000) % 2) {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, meshtastic::l10n::getString(meshtastic::l10n::StringKey::PleaseWait));
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
|
||||
} else {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, meshtastic::l10n::getString(meshtastic::l10n::StringKey::PleaseWait));
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,12 +919,9 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
||||
display->setColor(BLACK);
|
||||
int yOffset = 3;
|
||||
if (current_notification_type == notificationTypeEnum::node_picker) {
|
||||
if (isCJKLanguage())
|
||||
drawBannerText(display, textX, lineY - yOffset, lineBuffer);
|
||||
else
|
||||
UIRenderer::drawStringWithEmotes(display, textX, lineY - yOffset, lineBuffer, FONT_HEIGHT_SMALL, 1, false);
|
||||
UIRenderer::drawStringWithEmotes(display, textX, lineY - yOffset, lineBuffer, FONT_HEIGHT_SMALL, 1, false);
|
||||
} else {
|
||||
drawBannerText(display, textX, lineY - yOffset, lineBuffer);
|
||||
display->drawString(textX, lineY - yOffset, lineBuffer);
|
||||
}
|
||||
display->setColor(WHITE);
|
||||
lineY += (thisLineHeight - 2 - background_yOffset);
|
||||
@@ -969,12 +943,9 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
||||
int groupStartX = boxLeft + (boxWidth - totalWidth) / 2;
|
||||
|
||||
if (current_notification_type == notificationTypeEnum::node_picker) {
|
||||
if (isCJKLanguage())
|
||||
drawBannerText(display, groupStartX, lineY, lineBuffer);
|
||||
else
|
||||
UIRenderer::drawStringWithEmotes(display, groupStartX, lineY, lineBuffer, FONT_HEIGHT_SMALL, 1, false);
|
||||
UIRenderer::drawStringWithEmotes(display, groupStartX, lineY, lineBuffer, FONT_HEIGHT_SMALL, 1, false);
|
||||
} else {
|
||||
drawBannerText(display, groupStartX, lineY, lineBuffer);
|
||||
display->drawString(groupStartX, lineY, lineBuffer);
|
||||
}
|
||||
|
||||
int baseX = groupStartX + textWidth + gap;
|
||||
@@ -1006,12 +977,9 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
||||
}
|
||||
} else {
|
||||
if (current_notification_type == notificationTypeEnum::node_picker) {
|
||||
if (isCJKLanguage())
|
||||
drawBannerText(display, textX, lineY, lineBuffer);
|
||||
else
|
||||
UIRenderer::drawStringWithEmotes(display, textX, lineY, lineBuffer, FONT_HEIGHT_SMALL, 1, false);
|
||||
UIRenderer::drawStringWithEmotes(display, textX, lineY, lineBuffer, FONT_HEIGHT_SMALL, 1, false);
|
||||
} else {
|
||||
drawBannerText(display, textX, lineY, lineBuffer);
|
||||
display->drawString(textX, lineY, lineBuffer);
|
||||
}
|
||||
}
|
||||
lineY += thisLineHeight;
|
||||
@@ -1041,24 +1009,24 @@ void NotificationRenderer::drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisp
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
|
||||
char tempBuf[40];
|
||||
snprintf(tempBuf, sizeof(tempBuf), "%s #%d", meshtastic::l10n::getString(meshtastic::l10n::StringKey::CriticalFault), error_code);
|
||||
char tempBuf[24];
|
||||
snprintf(tempBuf, sizeof(tempBuf), "Critical fault #%d", error_code);
|
||||
display->drawString(0 + x, 0 + y, tempBuf);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, meshtastic::l10n::getString(meshtastic::l10n::StringKey::ForHelpVisit));
|
||||
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please visit \nmeshtastic.org");
|
||||
}
|
||||
|
||||
void NotificationRenderer::drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(64 + x, y, meshtastic::l10n::getString(meshtastic::l10n::StringKey::Updating));
|
||||
display->drawString(64 + x, y, "Updating");
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->drawStringMaxWidth(0 + x, 2 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(),
|
||||
meshtastic::l10n::getString(meshtastic::l10n::StringKey::PleaseBePatient));
|
||||
"Please be patient and do not power off.");
|
||||
}
|
||||
|
||||
void NotificationRenderer::drawTextInput(OLEDDisplay *display, OLEDDisplayUiState *state)
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
// Chinese font data (VLW format) for OLEDDisplay-based TFT rendering via LovyanGFX.
|
||||
//
|
||||
// HOW TO GENERATE FONT DATA:
|
||||
//
|
||||
// Option 1: Adafruit GFX fontconvert (simpler, fewer glyphs)
|
||||
// brew install adafruitnrf52-gfx-fontconvert # macOS
|
||||
// fontconvert NotoSansSC-Regular.ttf 16 > zh_cn_16.h
|
||||
// The output is a GFXfont struct. LovyanGFX can use this via ft_gfx type.
|
||||
//
|
||||
// Option 2: LovyanGFX VLW format (recommended, more features)
|
||||
// Use the LovyanGFX font converter script to generate a .vlw file from TTF
|
||||
// Then embed the .vlw binary as a byte array using xxd:
|
||||
// xxd -i zh_font_16.vlw > zh_font_16_data.h
|
||||
//
|
||||
// Option 3: Use BDF fonts (free, text-based)
|
||||
// WenQuanYi bitmap fonts: http://wenq.org/
|
||||
// Convert BDF to VLW using LovyanGFX tools
|
||||
//
|
||||
// FONT SIZE GUIDELINES:
|
||||
// - 16px: Minimum readable Chinese on 320x240 TFT (~20 chars per line)
|
||||
// - 20px: Better readability, ~16 chars per line
|
||||
// - 24px: Title/header text, ~13 chars per line
|
||||
//
|
||||
// CHARACTER SET RECOMMENDATIONS:
|
||||
// - GB2312 Level 1: 3755 commonly used simplified Chinese characters
|
||||
// - Plus ASCII 0x20-0x7E for punctuation and Latin characters
|
||||
//
|
||||
// PLACEHOLDER DATA - Replace with generated font binary:
|
||||
|
||||
#include "OLEDDisplayFontsZH.h"
|
||||
|
||||
// Placeholder font data.
|
||||
// Replace with actual generated VLW/Gfx font binary from a Chinese TTF file.
|
||||
// The array below is intentionally minimal - it won't render any characters
|
||||
// until real font data is provided.
|
||||
const uint8_t FontZH_CN_16[] = {
|
||||
// VLW font file magic header would go here
|
||||
// Format: 0x00 0x00 ...
|
||||
// Replace with output from: xxd -i your_chinese_font.vlw
|
||||
};
|
||||
const uint32_t FontZH_CN_16_size = sizeof(FontZH_CN_16);
|
||||
|
||||
const uint8_t FontZH_TW_16[] = {
|
||||
// Traditional Chinese VLW font data placeholder
|
||||
};
|
||||
const uint32_t FontZH_TW_16_size = sizeof(FontZH_TW_16);
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Chinese Simplified font - VLW format (to be generated from TTF)
|
||||
//
|
||||
// HOW TO GENERATE:
|
||||
// 1. Download NotoSansSC-Regular.ttf (or any open-source Chinese font)
|
||||
// 2. Use Adafruit fontconvert tool:
|
||||
// ./fontconvert NotoSansSC-Regular.ttf 16 > zh_cn_16_pt.h
|
||||
// 3. Copy the resulting binary data (GFXfont struct bytes) into the array below
|
||||
//
|
||||
// For LovyanGFX VLW font format, use:
|
||||
// - The binary VLW file can be embedded as a const uint8_t[] array
|
||||
// - Loaded with tft->loadFont(zh_font_data_array)
|
||||
|
||||
extern const uint8_t FontZH_CN_16[];
|
||||
extern const uint32_t FontZH_CN_16_size;
|
||||
|
||||
// Chinese Traditional font (VLW format)
|
||||
extern const uint8_t FontZH_TW_16[];
|
||||
extern const uint32_t FontZH_TW_16_size;
|
||||
@@ -1,20 +0,0 @@
|
||||
#include "Strings.h"
|
||||
#include "Strings_EN.h"
|
||||
#include "Strings_ZH.h"
|
||||
|
||||
namespace meshtastic
|
||||
{
|
||||
namespace l10n
|
||||
{
|
||||
|
||||
meshtastic_Language currentDisplayLanguage = meshtastic_Language_ENGLISH;
|
||||
|
||||
const char *getString(StringKey key, meshtastic_Language lang)
|
||||
{
|
||||
if (lang == meshtastic_Language_SIMPLIFIED_CHINESE || lang == meshtastic_Language_TRADITIONAL_CHINESE)
|
||||
return getStringZH(key);
|
||||
return getStringEN(key);
|
||||
}
|
||||
|
||||
} // namespace l10n
|
||||
} // namespace meshtastic
|
||||
@@ -1,170 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "mesh/generated/meshtastic/device_ui.pb.h"
|
||||
|
||||
namespace meshtastic
|
||||
{
|
||||
namespace l10n
|
||||
{
|
||||
|
||||
enum class StringKey : uint8_t {
|
||||
Back,
|
||||
OK,
|
||||
GotIt,
|
||||
WelcomeToMeshtastic,
|
||||
SwipeToNavigate,
|
||||
ClickToNavigate,
|
||||
UseSelectButton,
|
||||
DeviceRole,
|
||||
RadioPreset,
|
||||
FrequencySlot,
|
||||
LoRaRegion,
|
||||
Client,
|
||||
ClientMute,
|
||||
LostAndFound,
|
||||
Tracker,
|
||||
Hour12,
|
||||
Hour24,
|
||||
ClockAction,
|
||||
ClockFace,
|
||||
TimeFormat,
|
||||
Timezone,
|
||||
MessageAction,
|
||||
Reply,
|
||||
ViewChats,
|
||||
UnmuteChannel,
|
||||
MuteChannel,
|
||||
Delete,
|
||||
ReadAloud,
|
||||
Brightness,
|
||||
FrameVisibility,
|
||||
DisplayUnits,
|
||||
MessageBubbles,
|
||||
Theme,
|
||||
Reboot,
|
||||
Shutdown,
|
||||
SwitchToMUI,
|
||||
DisplayOptions,
|
||||
Language,
|
||||
Chinese,
|
||||
English,
|
||||
NoGPS,
|
||||
GPSoff,
|
||||
GPSnotPresent,
|
||||
GPSisDisabled,
|
||||
Node,
|
||||
Hop,
|
||||
USB,
|
||||
BT_off,
|
||||
WiFi,
|
||||
WiFiNotConnected,
|
||||
WiFiConnected,
|
||||
SSID,
|
||||
LoRaInfo,
|
||||
LoRa,
|
||||
Role,
|
||||
Freq,
|
||||
ChUtil,
|
||||
System,
|
||||
Heap,
|
||||
PSRAM,
|
||||
Flash,
|
||||
SD,
|
||||
Ver,
|
||||
Up,
|
||||
ClientApp,
|
||||
NoConnected,
|
||||
LOCKED,
|
||||
ConnectToUnlock,
|
||||
Battery,
|
||||
Resuming,
|
||||
LastHeard,
|
||||
HopsSig,
|
||||
HopsSignal,
|
||||
Nodes,
|
||||
Distance,
|
||||
Bearings,
|
||||
CreatingSSLCert,
|
||||
PleaseWait,
|
||||
CriticalFault,
|
||||
ForHelpVisit,
|
||||
Updating,
|
||||
PleaseBePatient,
|
||||
RebootInProgress,
|
||||
PowerMenu,
|
||||
SystemMenu,
|
||||
ScreenOptions,
|
||||
WifiToggle,
|
||||
BluetoothToggle,
|
||||
NodeDbReset,
|
||||
ManageNode,
|
||||
RemoveFavorite,
|
||||
AddFavorite,
|
||||
TestMenu,
|
||||
TraceRoute,
|
||||
ThrottleMessage,
|
||||
MessageViewMode,
|
||||
DeleteMessages,
|
||||
NodeNameLength,
|
||||
GPSMenu,
|
||||
GPSToggle,
|
||||
GPSFormat,
|
||||
GPSSmartPosition,
|
||||
GPSUpdateInterval,
|
||||
GPSPositionBroadcast,
|
||||
CompassNorth,
|
||||
BuzzerMode,
|
||||
HamModeConfirm,
|
||||
LicensedToNormal,
|
||||
KeyVerification,
|
||||
FinalPrompt,
|
||||
RegionUnset,
|
||||
SelectRegionMessage,
|
||||
Rebooting,
|
||||
LoRaActions,
|
||||
Slot0,
|
||||
WithPreset,
|
||||
WithFreetext,
|
||||
DeleteOldest,
|
||||
DeleteThisChat,
|
||||
DeleteAll,
|
||||
DeleteAllChats,
|
||||
TemporarilyMute,
|
||||
Unmute,
|
||||
ToggleBacklight,
|
||||
SleepScreen,
|
||||
SendPosition,
|
||||
SendNodeInfo,
|
||||
NewPresetMsg,
|
||||
NewFreetextMsg,
|
||||
Notifications,
|
||||
Power,
|
||||
RebootShutdown,
|
||||
GoToChat,
|
||||
NewPreset,
|
||||
Favorite,
|
||||
UnmuteNotifications,
|
||||
MuteNotifications,
|
||||
UnignoreNode,
|
||||
IgnoreNode,
|
||||
NumberPicker,
|
||||
TestAnnounce,
|
||||
NodeActionsSettings,
|
||||
ShowNameLength,
|
||||
Bluetooth,
|
||||
NoMessages,
|
||||
COUNT
|
||||
};
|
||||
|
||||
extern meshtastic_Language currentDisplayLanguage;
|
||||
|
||||
const char *getString(StringKey key, meshtastic_Language lang);
|
||||
|
||||
inline const char *getString(StringKey key)
|
||||
{
|
||||
extern meshtastic_Language currentDisplayLanguage;
|
||||
return getString(key, currentDisplayLanguage);
|
||||
}
|
||||
|
||||
} // namespace l10n
|
||||
} // namespace meshtastic
|
||||
@@ -1,456 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Strings.h"
|
||||
|
||||
namespace meshtastic
|
||||
{
|
||||
namespace l10n
|
||||
{
|
||||
|
||||
// English string table
|
||||
// The strings are stored as const arrays to save RAM on constrained devices.
|
||||
// Each locale file defines the same set of strings in its own language.
|
||||
|
||||
static const char STR_BACK_EN[] = "Back";
|
||||
static const char STR_OK_EN[] = "OK";
|
||||
static const char STR_GOT_IT_EN[] = "Got it!";
|
||||
static const char STR_WELCOME_TO_MESHTASTIC_EN[] = "Welcome to Meshtastic!";
|
||||
static const char STR_SWIPE_TO_NAVIGATE_EN[] = "Swipe to navigate.";
|
||||
static const char STR_CLICK_TO_NAVIGATE_EN[] = "Click to navigate.";
|
||||
static const char STR_USE_SELECT_BUTTON_EN[] = "Use the Select button.";
|
||||
static const char STR_DEVICE_ROLE_EN[] = "Device Role";
|
||||
static const char STR_RADIO_PRESET_EN[] = "Radio Preset";
|
||||
static const char STR_FREQUENCY_SLOT_EN[] = "Frequency Slot";
|
||||
static const char STR_LORA_REGION_EN[] = "LoRa Region";
|
||||
static const char STR_CLIENT_EN[] = "Client";
|
||||
static const char STR_CLIENT_MUTE_EN[] = "Client Mute";
|
||||
static const char STR_LOST_AND_FOUND_EN[] = "Lost and Found";
|
||||
static const char STR_TRACKER_EN[] = "Tracker";
|
||||
static const char STR_12HOUR_EN[] = "12-hour";
|
||||
static const char STR_24HOUR_EN[] = "24-hour";
|
||||
static const char STR_CLOCK_ACTION_EN[] = "Clock Action";
|
||||
static const char STR_CLOCK_FACE_EN[] = "Clock Face";
|
||||
static const char STR_TIME_FORMAT_EN[] = "Time Format";
|
||||
static const char STR_TIMEZONE_EN[] = "Timezone";
|
||||
static const char STR_MESSAGE_ACTION_EN[] = "Message Action";
|
||||
static const char STR_REPLY_EN[] = "Reply";
|
||||
static const char STR_VIEW_CHATS_EN[] = "View Chats";
|
||||
static const char STR_UNMUTE_CHANNEL_EN[] = "Unmute Channel";
|
||||
static const char STR_MUTE_CHANNEL_EN[] = "Mute Channel";
|
||||
static const char STR_DELETE_EN[] = "Delete";
|
||||
static const char STR_READ_ALOUD_EN[] = "Read Aloud";
|
||||
static const char STR_BRIGHTNESS_EN[] = "Brightness";
|
||||
static const char STR_FRAME_VISIBILITY_EN[] = "Frame Visibility";
|
||||
static const char STR_DISPLAY_UNITS_EN[] = "Display Units";
|
||||
static const char STR_MESSAGE_BUBBLES_EN[] = "Message Bubbles";
|
||||
static const char STR_THEME_EN[] = "Theme";
|
||||
static const char STR_REBOOT_EN[] = "Reboot";
|
||||
static const char STR_SHUTDOWN_EN[] = "Shutdown";
|
||||
static const char STR_SWITCH_TO_MUI_EN[] = "Switch to MUI";
|
||||
static const char STR_DISPLAY_OPTIONS_EN[] = "Display Options";
|
||||
static const char STR_LANGUAGE_EN[] = "Language";
|
||||
static const char STR_CHINESE_EN[] = "Chinese";
|
||||
static const char STR_ENGLISH_EN[] = "English";
|
||||
static const char STR_NO_GPS_EN[] = "No GPS";
|
||||
static const char STR_GPS_OFF_EN[] = "GPS off";
|
||||
static const char STR_GPS_NOT_PRESENT_EN[] = "GPS not present";
|
||||
static const char STR_GPS_IS_DISABLED_EN[] = "GPS is disabled";
|
||||
static const char STR_NODE_EN[] = "Node";
|
||||
static const char STR_HOP_EN[] = "Hop:";
|
||||
static const char STR_USB_EN[] = "USB";
|
||||
static const char STR_BT_OFF_EN[] = "BT off";
|
||||
static const char STR_WIFI_EN[] = "WiFi";
|
||||
static const char STR_WIFI_NOT_CONNECTED_EN[] = "WiFi: Not Connected";
|
||||
static const char STR_WIFI_CONNECTED_EN[] = "WiFi: Connected";
|
||||
static const char STR_SSID_EN[] = "SSID:";
|
||||
static const char STR_LORA_INFO_EN[] = "LoRa Info";
|
||||
static const char STR_LORA_EN[] = "LoRa";
|
||||
static const char STR_ROLE_EN[] = "Role:";
|
||||
static const char STR_FREQ_EN[] = "Freq:";
|
||||
static const char STR_CHUTIL_EN[] = "ChUtil";
|
||||
static const char STR_SYSTEM_EN[] = "System";
|
||||
static const char STR_HEAP_EN[] = "Heap:";
|
||||
static const char STR_PSRAM_EN[] = "PSRAM:";
|
||||
static const char STR_FLASH_EN[] = "Flash:";
|
||||
static const char STR_SD_EN[] = "SD:";
|
||||
static const char STR_VER_EN[] = "Ver:";
|
||||
static const char STR_UP_EN[] = "Up:";
|
||||
static const char STR_CLIENT_APP_EN[] = "Client";
|
||||
static const char STR_NO_CONNECTED_EN[] = "No Connected";
|
||||
static const char STR_LOCKED_EN[] = "LOCKED";
|
||||
static const char STR_CONNECT_TO_UNLOCK_EN[] = "Connect to unlock";
|
||||
static const char STR_BATTERY_EN[] = "Battery";
|
||||
static const char STR_RESUMING_EN[] = "Resuming...";
|
||||
static const char STR_LAST_HEARD_EN[] = "Last Heard";
|
||||
static const char STR_HOPS_SIG_EN[] = "Hops/Sig";
|
||||
static const char STR_HOPS_SIGNAL_EN[] = "Hops/Signal";
|
||||
static const char STR_NODES_EN[] = "Nodes";
|
||||
static const char STR_DISTANCE_EN[] = "Distance";
|
||||
static const char STR_BEARINGS_EN[] = "Bearings";
|
||||
static const char STR_CREATING_SSL_EN[] = "Creating SSL certificate";
|
||||
static const char STR_PLEASE_WAIT_EN[] = "Please wait . . .";
|
||||
static const char STR_CRITICAL_FAULT_EN[] = "Critical fault";
|
||||
static const char STR_FOR_HELP_VISIT_EN[] = "For help, please visit";
|
||||
static const char STR_UPDATING_EN[] = "Updating";
|
||||
static const char STR_PLEASE_BE_PATIENT_EN[] = "Please be patient and do not power off.";
|
||||
static const char STR_REBOOT_IN_PROGRESS_EN[] = "Reboot in progress...";
|
||||
static const char STR_POWER_MENU_EN[] = "Power";
|
||||
static const char STR_SYSTEM_MENU_EN[] = "System";
|
||||
static const char STR_SCREEN_OPTIONS_EN[] = "Screen";
|
||||
static const char STR_WIFI_TOGGLE_EN[] = "WiFi";
|
||||
static const char STR_BLUETOOTH_TOGGLE_EN[] = "Bluetooth";
|
||||
static const char STR_NODE_DB_RESET_EN[] = "Reset NodeDB";
|
||||
static const char STR_MANAGE_NODE_EN[] = "Manage Node";
|
||||
static const char STR_REMOVE_FAVORITE_EN[] = "Remove Favorite";
|
||||
static const char STR_ADD_FAVORITE_EN[] = "Add Favorite";
|
||||
static const char STR_TEST_MENU_EN[] = "Test";
|
||||
static const char STR_TRACE_ROUTE_EN[] = "Trace Route";
|
||||
static const char STR_THROTTLE_MSG_EN[] = "Message Throttled";
|
||||
static const char STR_MSG_VIEW_MODE_EN[] = "View Mode";
|
||||
static const char STR_DELETE_MESSAGES_EN[] = "Delete Messages";
|
||||
static const char STR_NODE_NAME_LENGTH_EN[] = "Name Length";
|
||||
static const char STR_GPS_MENU_EN[] = "GPS";
|
||||
static const char STR_GPS_TOGGLE_EN[] = "GPS Toggle";
|
||||
static const char STR_GPS_FORMAT_EN[] = "GPS Format";
|
||||
static const char STR_GPS_SMART_POS_EN[] = "Smart Position";
|
||||
static const char STR_GPS_UPDATE_INTERVAL_EN[] = "Update Interval";
|
||||
static const char STR_GPS_POS_BCAST_EN[] = "Position Broadcast";
|
||||
static const char STR_COMPASS_NORTH_EN[] = "Compass North";
|
||||
static const char STR_BUZZER_MODE_EN[] = "Buzzer";
|
||||
static const char STR_HAM_MODE_EN[] = "Ham Mode";
|
||||
static const char STR_LICENSED_NORMAL_EN[] = "Normal Mode";
|
||||
static const char STR_KEY_VERIFY_EN[] = "Verify Key";
|
||||
static const char STR_REGION_UNSET_EN[] = "Select a Region";
|
||||
static const char STR_SELECT_REGION_EN[] = "Please select your LoRa region:";
|
||||
static const char STR_REBOOTING_EN[] = "Rebooting...";
|
||||
static const char STR_LORA_ACTIONS_EN[] = "LoRa Actions";
|
||||
static const char STR_SLOT0_EN[] = "Slot 0 (Auto)";
|
||||
static const char STR_WITH_PRESET_EN[] = "With Preset";
|
||||
static const char STR_WITH_FREETEXT_EN[] = "With Freetext";
|
||||
static const char STR_DELETE_OLDEST_EN[] = "Delete Oldest";
|
||||
static const char STR_DELETE_THIS_CHAT_EN[] = "Delete This Chat";
|
||||
static const char STR_DELETE_ALL_EN[] = "Delete All";
|
||||
static const char STR_DELETE_ALL_CHATS_EN[] = "Delete All Chats";
|
||||
static const char STR_TEMPORARILY_MUTE_EN[] = "Temporarily Mute";
|
||||
static const char STR_UNMUTE_EN[] = "Unmute";
|
||||
static const char STR_TOGGLE_BACKLIGHT_EN[] = "Toggle Backlight";
|
||||
static const char STR_SLEEP_SCREEN_EN[] = "Sleep Screen";
|
||||
static const char STR_SEND_POSITION_EN[] = "Send Position";
|
||||
static const char STR_SEND_NODE_INFO_EN[] = "Send Node Info";
|
||||
static const char STR_NEW_PRESET_MSG_EN[] = "New Preset Msg";
|
||||
static const char STR_NEW_FREETEXT_MSG_EN[] = "New Freetext Msg";
|
||||
static const char STR_NOTIFICATIONS_EN[] = "Notifications";
|
||||
static const char STR_POWER_EN[] = "Power";
|
||||
static const char STR_REBOOT_SHUTDOWN_EN[] = "Reboot/Shutdown";
|
||||
static const char STR_GO_TO_CHAT_EN[] = "Go To Chat";
|
||||
static const char STR_NEW_PRESET_EN[] = "New Preset";
|
||||
static const char STR_FAVORITE_EN[] = "Favorite";
|
||||
static const char STR_UNMUTE_NOTIFICATIONS_EN[] = "Unmute Notifications";
|
||||
static const char STR_MUTE_NOTIFICATIONS_EN[] = "Mute Notifications";
|
||||
static const char STR_UNIGNORE_NODE_EN[] = "Unignore Node";
|
||||
static const char STR_IGNORE_NODE_EN[] = "Ignore Node";
|
||||
static const char STR_NUMBER_PICKER_EN[] = "Number Picker";
|
||||
static const char STR_TEST_ANNOUNCE_EN[] = "Test Announce";
|
||||
static const char STR_NODE_ACTIONS_EN[] = "Node Actions / Settings";
|
||||
static const char STR_SHOW_NAME_LENGTH_EN[] = "Show Long/Short Name";
|
||||
static const char STR_BLUETOOTH_EN[] = "Bluetooth";
|
||||
static const char STR_NO_MESSAGES_EN[] = "No messages";
|
||||
|
||||
inline const char *getStringEN(StringKey key)
|
||||
{
|
||||
switch (key) {
|
||||
case StringKey::Back:
|
||||
return STR_BACK_EN;
|
||||
case StringKey::OK:
|
||||
return STR_OK_EN;
|
||||
case StringKey::GotIt:
|
||||
return STR_GOT_IT_EN;
|
||||
case StringKey::WelcomeToMeshtastic:
|
||||
return STR_WELCOME_TO_MESHTASTIC_EN;
|
||||
case StringKey::SwipeToNavigate:
|
||||
return STR_SWIPE_TO_NAVIGATE_EN;
|
||||
case StringKey::ClickToNavigate:
|
||||
return STR_CLICK_TO_NAVIGATE_EN;
|
||||
case StringKey::UseSelectButton:
|
||||
return STR_USE_SELECT_BUTTON_EN;
|
||||
case StringKey::DeviceRole:
|
||||
return STR_DEVICE_ROLE_EN;
|
||||
case StringKey::RadioPreset:
|
||||
return STR_RADIO_PRESET_EN;
|
||||
case StringKey::FrequencySlot:
|
||||
return STR_FREQUENCY_SLOT_EN;
|
||||
case StringKey::LoRaRegion:
|
||||
return STR_LORA_REGION_EN;
|
||||
case StringKey::Client:
|
||||
return STR_CLIENT_EN;
|
||||
case StringKey::ClientMute:
|
||||
return STR_CLIENT_MUTE_EN;
|
||||
case StringKey::LostAndFound:
|
||||
return STR_LOST_AND_FOUND_EN;
|
||||
case StringKey::Tracker:
|
||||
return STR_TRACKER_EN;
|
||||
case StringKey::Hour12:
|
||||
return STR_12HOUR_EN;
|
||||
case StringKey::Hour24:
|
||||
return STR_24HOUR_EN;
|
||||
case StringKey::ClockAction:
|
||||
return STR_CLOCK_ACTION_EN;
|
||||
case StringKey::ClockFace:
|
||||
return STR_CLOCK_FACE_EN;
|
||||
case StringKey::TimeFormat:
|
||||
return STR_TIME_FORMAT_EN;
|
||||
case StringKey::Timezone:
|
||||
return STR_TIMEZONE_EN;
|
||||
case StringKey::MessageAction:
|
||||
return STR_MESSAGE_ACTION_EN;
|
||||
case StringKey::Reply:
|
||||
return STR_REPLY_EN;
|
||||
case StringKey::ViewChats:
|
||||
return STR_VIEW_CHATS_EN;
|
||||
case StringKey::UnmuteChannel:
|
||||
return STR_UNMUTE_CHANNEL_EN;
|
||||
case StringKey::MuteChannel:
|
||||
return STR_MUTE_CHANNEL_EN;
|
||||
case StringKey::Delete:
|
||||
return STR_DELETE_EN;
|
||||
case StringKey::ReadAloud:
|
||||
return STR_READ_ALOUD_EN;
|
||||
case StringKey::Brightness:
|
||||
return STR_BRIGHTNESS_EN;
|
||||
case StringKey::FrameVisibility:
|
||||
return STR_FRAME_VISIBILITY_EN;
|
||||
case StringKey::DisplayUnits:
|
||||
return STR_DISPLAY_UNITS_EN;
|
||||
case StringKey::MessageBubbles:
|
||||
return STR_MESSAGE_BUBBLES_EN;
|
||||
case StringKey::Theme:
|
||||
return STR_THEME_EN;
|
||||
case StringKey::Reboot:
|
||||
return STR_REBOOT_EN;
|
||||
case StringKey::Shutdown:
|
||||
return STR_SHUTDOWN_EN;
|
||||
case StringKey::SwitchToMUI:
|
||||
return STR_SWITCH_TO_MUI_EN;
|
||||
case StringKey::DisplayOptions:
|
||||
return STR_DISPLAY_OPTIONS_EN;
|
||||
case StringKey::Language:
|
||||
return STR_LANGUAGE_EN;
|
||||
case StringKey::Chinese:
|
||||
return STR_CHINESE_EN;
|
||||
case StringKey::English:
|
||||
return STR_ENGLISH_EN;
|
||||
case StringKey::NoGPS:
|
||||
return STR_NO_GPS_EN;
|
||||
case StringKey::GPSoff:
|
||||
return STR_GPS_OFF_EN;
|
||||
case StringKey::GPSnotPresent:
|
||||
return STR_GPS_NOT_PRESENT_EN;
|
||||
case StringKey::GPSisDisabled:
|
||||
return STR_GPS_IS_DISABLED_EN;
|
||||
case StringKey::Node:
|
||||
return STR_NODE_EN;
|
||||
case StringKey::Hop:
|
||||
return STR_HOP_EN;
|
||||
case StringKey::USB:
|
||||
return STR_USB_EN;
|
||||
case StringKey::BT_off:
|
||||
return STR_BT_OFF_EN;
|
||||
case StringKey::WiFi:
|
||||
return STR_WIFI_EN;
|
||||
case StringKey::WiFiNotConnected:
|
||||
return STR_WIFI_NOT_CONNECTED_EN;
|
||||
case StringKey::WiFiConnected:
|
||||
return STR_WIFI_CONNECTED_EN;
|
||||
case StringKey::SSID:
|
||||
return STR_SSID_EN;
|
||||
case StringKey::LoRaInfo:
|
||||
return STR_LORA_INFO_EN;
|
||||
case StringKey::LoRa:
|
||||
return STR_LORA_EN;
|
||||
case StringKey::Role:
|
||||
return STR_ROLE_EN;
|
||||
case StringKey::Freq:
|
||||
return STR_FREQ_EN;
|
||||
case StringKey::ChUtil:
|
||||
return STR_CHUTIL_EN;
|
||||
case StringKey::System:
|
||||
return STR_SYSTEM_EN;
|
||||
case StringKey::Heap:
|
||||
return STR_HEAP_EN;
|
||||
case StringKey::PSRAM:
|
||||
return STR_PSRAM_EN;
|
||||
case StringKey::Flash:
|
||||
return STR_FLASH_EN;
|
||||
case StringKey::SD:
|
||||
return STR_SD_EN;
|
||||
case StringKey::Ver:
|
||||
return STR_VER_EN;
|
||||
case StringKey::Up:
|
||||
return STR_UP_EN;
|
||||
case StringKey::ClientApp:
|
||||
return STR_CLIENT_APP_EN;
|
||||
case StringKey::NoConnected:
|
||||
return STR_NO_CONNECTED_EN;
|
||||
case StringKey::LOCKED:
|
||||
return STR_LOCKED_EN;
|
||||
case StringKey::ConnectToUnlock:
|
||||
return STR_CONNECT_TO_UNLOCK_EN;
|
||||
case StringKey::Battery:
|
||||
return STR_BATTERY_EN;
|
||||
case StringKey::Resuming:
|
||||
return STR_RESUMING_EN;
|
||||
case StringKey::LastHeard:
|
||||
return STR_LAST_HEARD_EN;
|
||||
case StringKey::HopsSig:
|
||||
return STR_HOPS_SIG_EN;
|
||||
case StringKey::HopsSignal:
|
||||
return STR_HOPS_SIGNAL_EN;
|
||||
case StringKey::Nodes:
|
||||
return STR_NODES_EN;
|
||||
case StringKey::Distance:
|
||||
return STR_DISTANCE_EN;
|
||||
case StringKey::Bearings:
|
||||
return STR_BEARINGS_EN;
|
||||
case StringKey::CreatingSSLCert:
|
||||
return STR_CREATING_SSL_EN;
|
||||
case StringKey::PleaseWait:
|
||||
return STR_PLEASE_WAIT_EN;
|
||||
case StringKey::CriticalFault:
|
||||
return STR_CRITICAL_FAULT_EN;
|
||||
case StringKey::ForHelpVisit:
|
||||
return STR_FOR_HELP_VISIT_EN;
|
||||
case StringKey::Updating:
|
||||
return STR_UPDATING_EN;
|
||||
case StringKey::PleaseBePatient:
|
||||
return STR_PLEASE_BE_PATIENT_EN;
|
||||
case StringKey::RebootInProgress:
|
||||
return STR_REBOOT_IN_PROGRESS_EN;
|
||||
case StringKey::PowerMenu:
|
||||
return STR_POWER_MENU_EN;
|
||||
case StringKey::SystemMenu:
|
||||
return STR_SYSTEM_MENU_EN;
|
||||
case StringKey::ScreenOptions:
|
||||
return STR_SCREEN_OPTIONS_EN;
|
||||
case StringKey::WifiToggle:
|
||||
return STR_WIFI_TOGGLE_EN;
|
||||
case StringKey::BluetoothToggle:
|
||||
return STR_BLUETOOTH_TOGGLE_EN;
|
||||
case StringKey::NodeDbReset:
|
||||
return STR_NODE_DB_RESET_EN;
|
||||
case StringKey::ManageNode:
|
||||
return STR_MANAGE_NODE_EN;
|
||||
case StringKey::RemoveFavorite:
|
||||
return STR_REMOVE_FAVORITE_EN;
|
||||
case StringKey::AddFavorite:
|
||||
return STR_ADD_FAVORITE_EN;
|
||||
case StringKey::TestMenu:
|
||||
return STR_TEST_MENU_EN;
|
||||
case StringKey::TraceRoute:
|
||||
return STR_TRACE_ROUTE_EN;
|
||||
case StringKey::ThrottleMessage:
|
||||
return STR_THROTTLE_MSG_EN;
|
||||
case StringKey::MessageViewMode:
|
||||
return STR_MSG_VIEW_MODE_EN;
|
||||
case StringKey::DeleteMessages:
|
||||
return STR_DELETE_MESSAGES_EN;
|
||||
case StringKey::NodeNameLength:
|
||||
return STR_NODE_NAME_LENGTH_EN;
|
||||
case StringKey::GPSMenu:
|
||||
return STR_GPS_MENU_EN;
|
||||
case StringKey::GPSToggle:
|
||||
return STR_GPS_TOGGLE_EN;
|
||||
case StringKey::GPSFormat:
|
||||
return STR_GPS_FORMAT_EN;
|
||||
case StringKey::GPSSmartPosition:
|
||||
return STR_GPS_SMART_POS_EN;
|
||||
case StringKey::GPSUpdateInterval:
|
||||
return STR_GPS_UPDATE_INTERVAL_EN;
|
||||
case StringKey::GPSPositionBroadcast:
|
||||
return STR_GPS_POS_BCAST_EN;
|
||||
case StringKey::CompassNorth:
|
||||
return STR_COMPASS_NORTH_EN;
|
||||
case StringKey::BuzzerMode:
|
||||
return STR_BUZZER_MODE_EN;
|
||||
case StringKey::HamModeConfirm:
|
||||
return STR_HAM_MODE_EN;
|
||||
case StringKey::LicensedToNormal:
|
||||
return STR_LICENSED_NORMAL_EN;
|
||||
case StringKey::KeyVerification:
|
||||
return STR_KEY_VERIFY_EN;
|
||||
case StringKey::RegionUnset:
|
||||
return STR_REGION_UNSET_EN;
|
||||
case StringKey::SelectRegionMessage:
|
||||
return STR_SELECT_REGION_EN;
|
||||
case StringKey::Rebooting:
|
||||
return STR_REBOOTING_EN;
|
||||
case StringKey::LoRaActions:
|
||||
return STR_LORA_ACTIONS_EN;
|
||||
case StringKey::Slot0:
|
||||
return STR_SLOT0_EN;
|
||||
case StringKey::WithPreset:
|
||||
return STR_WITH_PRESET_EN;
|
||||
case StringKey::WithFreetext:
|
||||
return STR_WITH_FREETEXT_EN;
|
||||
case StringKey::DeleteOldest:
|
||||
return STR_DELETE_OLDEST_EN;
|
||||
case StringKey::DeleteThisChat:
|
||||
return STR_DELETE_THIS_CHAT_EN;
|
||||
case StringKey::DeleteAll:
|
||||
return STR_DELETE_ALL_EN;
|
||||
case StringKey::DeleteAllChats:
|
||||
return STR_DELETE_ALL_CHATS_EN;
|
||||
case StringKey::TemporarilyMute:
|
||||
return STR_TEMPORARILY_MUTE_EN;
|
||||
case StringKey::Unmute:
|
||||
return STR_UNMUTE_EN;
|
||||
case StringKey::ToggleBacklight:
|
||||
return STR_TOGGLE_BACKLIGHT_EN;
|
||||
case StringKey::SleepScreen:
|
||||
return STR_SLEEP_SCREEN_EN;
|
||||
case StringKey::SendPosition:
|
||||
return STR_SEND_POSITION_EN;
|
||||
case StringKey::SendNodeInfo:
|
||||
return STR_SEND_NODE_INFO_EN;
|
||||
case StringKey::NewPresetMsg:
|
||||
return STR_NEW_PRESET_MSG_EN;
|
||||
case StringKey::NewFreetextMsg:
|
||||
return STR_NEW_FREETEXT_MSG_EN;
|
||||
case StringKey::Notifications:
|
||||
return STR_NOTIFICATIONS_EN;
|
||||
case StringKey::Power:
|
||||
return STR_POWER_EN;
|
||||
case StringKey::RebootShutdown:
|
||||
return STR_REBOOT_SHUTDOWN_EN;
|
||||
case StringKey::GoToChat:
|
||||
return STR_GO_TO_CHAT_EN;
|
||||
case StringKey::NewPreset:
|
||||
return STR_NEW_PRESET_EN;
|
||||
case StringKey::Favorite:
|
||||
return STR_FAVORITE_EN;
|
||||
case StringKey::UnmuteNotifications:
|
||||
return STR_UNMUTE_NOTIFICATIONS_EN;
|
||||
case StringKey::MuteNotifications:
|
||||
return STR_MUTE_NOTIFICATIONS_EN;
|
||||
case StringKey::UnignoreNode:
|
||||
return STR_UNIGNORE_NODE_EN;
|
||||
case StringKey::IgnoreNode:
|
||||
return STR_IGNORE_NODE_EN;
|
||||
case StringKey::NumberPicker:
|
||||
return STR_NUMBER_PICKER_EN;
|
||||
case StringKey::TestAnnounce:
|
||||
return STR_TEST_ANNOUNCE_EN;
|
||||
case StringKey::NodeActionsSettings:
|
||||
return STR_NODE_ACTIONS_EN;
|
||||
case StringKey::ShowNameLength:
|
||||
return STR_SHOW_NAME_LENGTH_EN;
|
||||
case StringKey::Bluetooth:
|
||||
return STR_BLUETOOTH_EN;
|
||||
case StringKey::NoMessages:
|
||||
return STR_NO_MESSAGES_EN;
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace l10n
|
||||
} // namespace meshtastic
|
||||
@@ -1,452 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Strings.h"
|
||||
|
||||
namespace meshtastic
|
||||
{
|
||||
namespace l10n
|
||||
{
|
||||
|
||||
static const char STR_BACK_ZH[] = "\xe8\xbf\x94\xe5\x9b\x9e";
|
||||
static const char STR_OK_ZH[] = "\xe7\xa1\xae\xe5\xae\x9a";
|
||||
static const char STR_GOT_IT_ZH[] = "\xe7\x9f\xa5\xe9\x81\x93\xe4\xba\x86";
|
||||
static const char STR_WELCOME_TO_MESHTASTIC_ZH[] = "\xe6\xac\xa2\xe8\xbf\x8e\xe4\xbd\xbf\xe7\x94\xa8 Meshtastic\xef\xbc\x81";
|
||||
static const char STR_SWIPE_TO_NAVIGATE_ZH[] = "\xe6\xbb\x91\xe5\x8a\xa8\xe4\xbb\xa5\xe5\xaf\xbc\xe8\x88\xaa\xe3\x80\x82";
|
||||
static const char STR_CLICK_TO_NAVIGATE_ZH[] = "\xe7\x82\xb9\xe5\x87\xbb\xe4\xbb\xa5\xe5\xaf\xbc\xe8\x88\xaa\xe3\x80\x82";
|
||||
static const char STR_USE_SELECT_BUTTON_ZH[] = "\xe4\xbd\xbf\xe7\x94\xa8\xe9\x80\x89\xe6\x8b\xa9\xe6\x8c\x89\xe9\x92\xae\xe3\x80\x82";
|
||||
static const char STR_DEVICE_ROLE_ZH[] = "\xe8\xae\xbe\xe5\xa4\x87\xe8\xa7\x92\xe8\x89\xb2";
|
||||
static const char STR_RADIO_PRESET_ZH[] = "\xe6\x97\xa0\xe7\xba\xbf\xe9\xa2\x84\xe8\xae\xbe";
|
||||
static const char STR_FREQUENCY_SLOT_ZH[] = "\xe9\xa2\x91\xe7\x8e\x87\xe6\xa7\xbd\xe4\xbd\x8d";
|
||||
static const char STR_LORA_REGION_ZH[] = "LoRa \xe5\x9c\xb0\xe5\x8c\xba";
|
||||
static const char STR_CLIENT_ZH[] = "\xe5\xae\xa2\xe6\x88\xb7\xe7\xab\xaf";
|
||||
static const char STR_CLIENT_MUTE_ZH[] = "\xe9\x9d\x99\xe9\x9f\xb3\xe5\xae\xa2\xe6\x88\xb7\xe7\xab\xaf";
|
||||
static const char STR_LOST_AND_FOUND_ZH[] = "\xe5\xa4\xb1\xe7\x89\xa9\xe6\x8b\x9b\xe9\xa2\x86";
|
||||
static const char STR_TRACKER_ZH[] = "\xe8\xbf\xbd\xe8\xb8\xaa\xe5\x99\xa8";
|
||||
static const char STR_12HOUR_ZH[] = "12 \xe5\xb0\x8f\xe6\x97\xb6\xe5\x88\xb6";
|
||||
static const char STR_24HOUR_ZH[] = "24 \xe5\xb0\x8f\xe6\x97\xb6\xe5\x88\xb6";
|
||||
static const char STR_CLOCK_ACTION_ZH[] = "\xe6\x97\xb6\xe9\x92\x9f\xe6\x93\x8d\xe4\xbd\x9c";
|
||||
static const char STR_CLOCK_FACE_ZH[] = "\xe6\x97\xb6\xe9\x92\x9f\xe6\xa0\xb7\xe5\xbc\x8f";
|
||||
static const char STR_TIME_FORMAT_ZH[] = "\xe6\x97\xb6\xe9\x97\xb4\xe6\xa0\xbc\xe5\xbc\x8f";
|
||||
static const char STR_TIMEZONE_ZH[] = "\xe6\x97\xb6\xe5\x8c\xba";
|
||||
static const char STR_MESSAGE_ACTION_ZH[] = "\xe6\xb6\x88\xe6\x81\xaf\xe6\x93\x8d\xe4\xbd\x9c";
|
||||
static const char STR_REPLY_ZH[] = "\xe5\x9b\x9e\xe5\xa4\x8d";
|
||||
static const char STR_VIEW_CHATS_ZH[] = "\xe6\x9f\xa5\xe7\x9c\x8b\xe8\x81\x8a\xe5\xa4\xa9";
|
||||
static const char STR_UNMUTE_CHANNEL_ZH[] = "\xe5\x8f\x96\xe6\xb6\x88\xe9\x9d\x99\xe9\x9f\xb3";
|
||||
static const char STR_MUTE_CHANNEL_ZH[] = "\xe9\x9d\x99\xe9\x9f\xb3\xe9\xa2\x91\xe9\x81\x93";
|
||||
static const char STR_DELETE_ZH[] = "\xe5\x88\xa0\xe9\x99\xa4";
|
||||
static const char STR_READ_ALOUD_ZH[] = "\xe5\xa4\xa7\xe5\xa3\xb0\xe6\x9c\x97\xe8\xaf\xbb";
|
||||
static const char STR_BRIGHTNESS_ZH[] = "\xe4\xba\xae\xe5\xba\xa6";
|
||||
static const char STR_FRAME_VISIBILITY_ZH[] = "\xe9\xa1\xb5\xe9\x9d\xa2\xe5\x8f\xaf\xe8\xa7\x81\xe6\x80\xa7";
|
||||
static const char STR_DISPLAY_UNITS_ZH[] = "\xe6\x98\xbe\xe7\xa4\xba\xe5\x8d\x95\xe4\xbd\x8d";
|
||||
static const char STR_MESSAGE_BUBBLES_ZH[] = "\xe6\xb6\x88\xe6\x81\xaf\xe6\xb0\x94\xe6\xb3\xa1";
|
||||
static const char STR_THEME_ZH[] = "\xe4\xb8\xbb\xe9\xa2\x98";
|
||||
static const char STR_REBOOT_ZH[] = "\xe9\x87\x8d\xe5\x90\xaf";
|
||||
static const char STR_SHUTDOWN_ZH[] = "\xe5\x85\xb3\xe6\x9c\xba";
|
||||
static const char STR_SWITCH_TO_MUI_ZH[] = "\xe5\x88\x87\xe6\x8d\xa2\xe5\x88\xb0 MUI";
|
||||
static const char STR_DISPLAY_OPTIONS_ZH[] = "\xe6\x98\xbe\xe7\xa4\xba\xe9\x80\x89\xe9\xa1\xb9";
|
||||
static const char STR_LANGUAGE_ZH[] = "\xe8\xaf\xad\xe8\xa8\x80";
|
||||
static const char STR_CHINESE_ZH[] = "\xe4\xb8\xad\xe6\x96\x87";
|
||||
static const char STR_ENGLISH_ZH[] = "\xe8\x8b\xb1\xe6\x96\x87";
|
||||
static const char STR_NO_GPS_ZH[] = "\xe6\x97\xa0 GPS";
|
||||
static const char STR_GPS_OFF_ZH[] = "GPS \xe5\xb7\xb2\xe5\x85\xb3\xe9\x97\xad";
|
||||
static const char STR_GPS_NOT_PRESENT_ZH[] = "GPS \xe4\xb8\x8d\xe5\xad\x98\xe5\x9c\xa8";
|
||||
static const char STR_GPS_IS_DISABLED_ZH[] = "GPS \xe5\xb7\xb2\xe7\xa6\x81\xe7\x94\xa8";
|
||||
static const char STR_NODE_ZH[] = "\xe8\x8a\x82\xe7\x82\xb9";
|
||||
static const char STR_HOP_ZH[] = "\xe8\xb7\xb3\xe6\x95\xb0:";
|
||||
static const char STR_USB_ZH[] = "USB";
|
||||
static const char STR_BT_OFF_ZH[] = "\xe8\x93\x9d\xe7\x89\x99\xe5\xb7\xb2\xe5\x85\xb3";
|
||||
static const char STR_WIFI_ZH[] = "WiFi";
|
||||
static const char STR_WIFI_NOT_CONNECTED_ZH[] = "WiFi: \xe6\x9c\xaa\xe8\xbf\x9e\xe6\x8e\xa5";
|
||||
static const char STR_WIFI_CONNECTED_ZH[] = "WiFi: \xe5\xb7\xb2\xe8\xbf\x9e\xe6\x8e\xa5";
|
||||
static const char STR_SSID_ZH[] = "SSID:";
|
||||
static const char STR_LORA_INFO_ZH[] = "LoRa \xe4\xbf\xa1\xe6\x81\xaf";
|
||||
static const char STR_LORA_ZH[] = "LoRa";
|
||||
static const char STR_ROLE_ZH[] = "\xe8\xa7\x92\xe8\x89\xb2:";
|
||||
static const char STR_FREQ_ZH[] = "\xe9\xa2\x91\xe7\x8e\x87:";
|
||||
static const char STR_CHUTIL_ZH[] = "\xe4\xbf\xa1\xe9\x81\x93\xe5\x88\xa9\xe7\x94\xa8";
|
||||
static const char STR_SYSTEM_ZH[] = "\xe7\xb3\xbb\xe7\xbb\x9f";
|
||||
static const char STR_HEAP_ZH[] = "\xe5\xa0\x86:";
|
||||
static const char STR_PSRAM_ZH[] = "PSRAM:";
|
||||
static const char STR_FLASH_ZH[] = "Flash:";
|
||||
static const char STR_SD_ZH[] = "SD:";
|
||||
static const char STR_VER_ZH[] = "\xe7\x89\x88\xe6\x9c\xac:";
|
||||
static const char STR_UP_ZH[] = "\xe8\xbf\x90\xe8\xa1\x8c:";
|
||||
static const char STR_CLIENT_APP_ZH[] = "\xe5\xae\xa2\xe6\x88\xb7\xe7\xab\xaf";
|
||||
static const char STR_NO_CONNECTED_ZH[] = "\xe6\x9c\xaa\xe8\xbf\x9e\xe6\x8e\xa5";
|
||||
static const char STR_LOCKED_ZH[] = "\xe5\xb7\xb2\xe9\x94\x81\xe5\xae\x9a";
|
||||
static const char STR_CONNECT_TO_UNLOCK_ZH[] = "\xe8\xbf\x9e\xe6\x8e\xa5\xe4\xbb\xa5\xe8\xa7\xa3\xe9\x94\x81";
|
||||
static const char STR_BATTERY_ZH[] = "\xe7\x94\xb5\xe6\xb1\xa0";
|
||||
static const char STR_RESUMING_ZH[] = "\xe6\xad\xa3\xe5\x9c\xa8\xe6\x81\xa2\xe5\xa4\x8d...";
|
||||
static const char STR_LAST_HEARD_ZH[] = "\xe6\x9c\x80\xe5\x90\x8e\xe5\x90\xac\xe5\x88\xb0";
|
||||
static const char STR_HOPS_SIG_ZH[] = "\xe8\xb7\xb3\xe6\x95\xb0/\xe4\xbf\xa1\xe5\x8f\xb7";
|
||||
static const char STR_HOPS_SIGNAL_ZH[] = "\xe8\xb7\xb3\xe6\x95\xb0/\xe4\xbf\xa1\xe5\x8f\xb7";
|
||||
static const char STR_NODES_ZH[] = "\xe8\x8a\x82\xe7\x82\xb9";
|
||||
static const char STR_DISTANCE_ZH[] = "\xe8\xb7\x9d\xe7\xa6\xbb";
|
||||
static const char STR_BEARINGS_ZH[] = "\xe6\x96\xb9\xe4\xbd\x8d";
|
||||
static const char STR_CREATING_SSL_ZH[] = "\xe6\xad\xa3\xe5\x9c\xa8\xe5\x88\x9b\xe5\xbb\xba SSL \xe8\xaf\x81\xe4\xb9\xa6";
|
||||
static const char STR_PLEASE_WAIT_ZH[] = "\xe8\xaf\xb7\xe7\xa8\x8d\xe5\x80\x99 . . .";
|
||||
static const char STR_CRITICAL_FAULT_ZH[] = "\xe4\xb8\xa5\xe9\x87\x8d\xe6\x95\x85\xe9\x9a\x9c";
|
||||
static const char STR_FOR_HELP_VISIT_ZH[] = "\xe8\xaf\xb7\xe8\xae\xbf\xe9\x97\xae\x4e\xe5\xb8\xae\xe5\x8a\xa9";
|
||||
static const char STR_UPDATING_ZH[] = "\xe6\xad\xa3\xe5\x9c\xa8\xe6\x9b\xb4\xe6\x96\xb0";
|
||||
static const char STR_PLEASE_BE_PATIENT_ZH[] = "\xe8\xaf\xb7\xe8\x80\x90\xe5\xbf\x83\xe7\xad\x89\xe5\xbe\x85\xef\xbc\x8c\xe4\xb8\x8d\xe8\xa6\x81\xe5\x85\xb3\xe9\x97\xad\xe7\x94\xb5\xe6\xba\x90\xe3\x80\x82";
|
||||
static const char STR_REBOOT_IN_PROGRESS_ZH[] = "\xe6\xad\xa3\xe5\x9c\xa8\xe9\x87\x8d\xe5\x90\xaf...";
|
||||
static const char STR_POWER_MENU_ZH[] = "\xe7\x94\xb5\xe6\xba\x90";
|
||||
static const char STR_SYSTEM_MENU_ZH[] = "\xe7\xb3\xbb\xe7\xbb\x9f";
|
||||
static const char STR_SCREEN_OPTIONS_ZH[] = "\xe5\xb1\x8f\xe5\xb9\x95";
|
||||
static const char STR_WIFI_TOGGLE_ZH[] = "WiFi";
|
||||
static const char STR_BLUETOOTH_TOGGLE_ZH[] = "\xe8\x93\x9d\xe7\x89\x99";
|
||||
static const char STR_NODE_DB_RESET_ZH[] = "\xe9\x87\x8d\xe7\xbd\xae\xe8\x8a\x82\xe7\x82\xb9\xe5\xba\x93";
|
||||
static const char STR_MANAGE_NODE_ZH[] = "\xe7\xae\xa1\xe7\x90\x86\xe8\x8a\x82\xe7\x82\xb9";
|
||||
static const char STR_REMOVE_FAVORITE_ZH[] = "\xe5\x8f\x96\xe6\xb6\x88\xe6\x94\xb6\xe8\x97\x8f";
|
||||
static const char STR_ADD_FAVORITE_ZH[] = "\xe6\xb7\xbb\xe5\x8a\xa0\xe6\x94\xb6\xe8\x97\x8f";
|
||||
static const char STR_TEST_MENU_ZH[] = "\xe6\xb5\x8b\xe8\xaf\x95";
|
||||
static const char STR_TRACE_ROUTE_ZH[] = "\xe8\xb7\xaf\xe7\x94\xb1\xe8\xbf\xbd\xe8\xb8\xaa";
|
||||
static const char STR_THROTTLE_MSG_ZH[] = "\xe6\xb6\x88\xe6\x81\xaf\xe5\xb7\xb2\xe9\x99\x90\xe6\xb5\x81";
|
||||
static const char STR_MSG_VIEW_MODE_ZH[] = "\xe6\x9f\xa5\xe7\x9c\x8b\xe6\xa8\xa1\xe5\xbc\x8f";
|
||||
static const char STR_DELETE_MESSAGES_ZH[] = "\xe5\x88\xa0\xe9\x99\xa4\xe6\xb6\x88\xe6\x81\xaf";
|
||||
static const char STR_NODE_NAME_LENGTH_ZH[] = "\xe5\x90\x8d\xe7\xa7\xb0\xe9\x95\xbf\xe5\xba\xa6";
|
||||
static const char STR_GPS_MENU_ZH[] = "GPS";
|
||||
static const char STR_GPS_TOGGLE_ZH[] = "GPS \xe5\xbc\x80\xe5\x85\xb3";
|
||||
static const char STR_GPS_FORMAT_ZH[] = "GPS \xe6\xa0\xbc\xe5\xbc\x8f";
|
||||
static const char STR_GPS_SMART_POS_ZH[] = "\xe6\x99\xba\xe8\x83\xbd\xe5\xae\x9a\xe4\xbd\x8d";
|
||||
static const char STR_GPS_UPDATE_INTERVAL_ZH[] = "\xe6\x9b\xb4\xe6\x96\xb0\xe9\x97\xb4\xe9\x9a\x94";
|
||||
static const char STR_GPS_POS_BCAST_ZH[] = "\xe4\xbd\x8d\xe7\xbd\xae\xe5\xb9\xbf\xe6\x92\xad";
|
||||
static const char STR_COMPASS_NORTH_ZH[] = "\xe6\x8c\x87\xe5\x8d\x97\xe9\x92\x88";
|
||||
static const char STR_BUZZER_MODE_ZH[] = "\xe8\x9c\x82\xe9\xb8\xa3\xe5\x99\xa8";
|
||||
static const char STR_HAM_MODE_ZH[] = "Ham \xe6\xa8\xa1\xe5\xbc\x8f";
|
||||
static const char STR_LICENSED_NORMAL_ZH[] = "\xe6\x99\xae\xe9\x80\x9a\xe6\xa8\xa1\xe5\xbc\x8f";
|
||||
static const char STR_KEY_VERIFY_ZH[] = "\xe9\xaa\x8c\xe8\xaf\x81\xe5\xaf\x86\xe9\x92\xa5";
|
||||
static const char STR_REGION_UNSET_ZH[] = "\xe8\xaf\xb7\xe9\x80\x89\xe6\x8b\xa9\xe5\x9c\xb0\xe5\x8c\xba";
|
||||
static const char STR_SELECT_REGION_ZH[] = "\xe8\xaf\xb7\xe9\x80\x89\xe6\x8b\xa9\xe6\x82\xa8\xe7\x9a\x84 LoRa \xe5\x8c\xba\xe5\x9f\x9f:";
|
||||
static const char STR_REBOOTING_ZH[] = "\xe6\xad\xa3\xe5\x9c\xa8\xe9\x87\x8d\xe5\x90\xaf...";
|
||||
static const char STR_LORA_ACTIONS_ZH[] = "LoRa \xe6\x93\x8d\xe4\xbd\x9c";
|
||||
static const char STR_SLOT0_ZH[] = "\xe6\xa7\xbd\xe4\xbd\x8d 0 (\xe8\x87\xaa\xe5\x8a\xa8)";
|
||||
static const char STR_WITH_PRESET_ZH[] = "\xe9\xa2\x84\xe8\xae\xbe\xe6\xb6\x88\xe6\x81\xaf";
|
||||
static const char STR_WITH_FREETEXT_ZH[] = "\xe8\x87\xaa\xe5\xae\x9a\xe4\xb9\x89";
|
||||
static const char STR_DELETE_OLDEST_ZH[] = "\xe5\x88\xa0\xe9\x99\xa4\xe6\x9c\x80\xe6\x97\xa7";
|
||||
static const char STR_DELETE_THIS_CHAT_ZH[] = "\xe5\x88\xa0\xe9\x99\xa4\xe6\xad\xa4\xe8\x81\x8a\xe5\xa4\xa9";
|
||||
static const char STR_DELETE_ALL_ZH[] = "\xe5\x88\xa0\xe9\x99\xa4\xe5\x85\xa8\xe9\x83\xa8";
|
||||
static const char STR_DELETE_ALL_CHATS_ZH[] = "\xe5\x88\xa0\xe9\x99\xa4\xe6\x89\x80\xe6\x9c\x89\xe8\x81\x8a\xe5\xa4\xa9";
|
||||
static const char STR_TEMPORARILY_MUTE_ZH[] = "\xe4\xb8\xb4\xe6\x97\xb6\xe9\x9d\x99\xe9\x9f\xb3";
|
||||
static const char STR_UNMUTE_ZH[] = "\xe5\x8f\x96\xe6\xb6\x88\xe9\x9d\x99\xe9\x9f\xb3";
|
||||
static const char STR_TOGGLE_BACKLIGHT_ZH[] = "\xe8\x83\x8c\xe5\x85\x89\xe5\xbc\x80\xe5\x85\xb3";
|
||||
static const char STR_SLEEP_SCREEN_ZH[] = "\xe4\xbc\x91\xe7\x9c\xa0\xe5\xb1\x8f\xe5\xb9\x95";
|
||||
static const char STR_SEND_POSITION_ZH[] = "\xe5\x8f\x91\xe9\x80\x81\xe4\xbd\x8d\xe7\xbd\xae";
|
||||
static const char STR_SEND_NODE_INFO_ZH[] = "\xe5\x8f\x91\xe9\x80\x81\xe8\x8a\x82\xe7\x82\xb9\xe4\xbf\xa1\xe6\x81\xaf";
|
||||
static const char STR_NEW_PRESET_MSG_ZH[] = "\xe6\x96\xb0\xe9\xa2\x84\xe8\xae\xbe\xe6\xb6\x88\xe6\x81\xaf";
|
||||
static const char STR_NEW_FREETEXT_MSG_ZH[] = "\xe6\x96\xb0\xe8\x87\xaa\xe5\xae\x9a\xe4\xb9\x89\xe6\xb6\x88\xe6\x81\xaf";
|
||||
static const char STR_NOTIFICATIONS_ZH[] = "\xe9\x80\x9a\xe7\x9f\xa5";
|
||||
static const char STR_POWER_ZH[] = "\xe7\x94\xb5\xe6\xba\x90";
|
||||
static const char STR_REBOOT_SHUTDOWN_ZH[] = "\xe9\x87\x8d\xe5\x90\xaf/\xe5\x85\xb3\xe6\x9c\xba";
|
||||
static const char STR_GO_TO_CHAT_ZH[] = "\xe8\xbf\x9b\xe5\x85\xa5\xe8\x81\x8a\xe5\xa4\xa9";
|
||||
static const char STR_NEW_PRESET_ZH[] = "\xe6\x96\xb0\xe9\xa2\x84\xe8\xae\xbe";
|
||||
static const char STR_FAVORITE_ZH[] = "\xe6\x94\xb6\xe8\x97\x8f";
|
||||
static const char STR_UNMUTE_NOTIFICATIONS_ZH[] = "\xe5\x8f\x96\xe6\xb6\x88\xe9\x80\x9a\xe7\x9f\xa5\xe9\x9d\x99\xe9\x9f\xb3";
|
||||
static const char STR_MUTE_NOTIFICATIONS_ZH[] = "\xe9\x80\x9a\xe7\x9f\xa5\xe9\x9d\x99\xe9\x9f\xb3";
|
||||
static const char STR_UNIGNORE_NODE_ZH[] = "\xe5\x8f\x96\xe6\xb6\x88\xe5\xbf\xbd\xe7\x95\xa5";
|
||||
static const char STR_IGNORE_NODE_ZH[] = "\xe5\xbf\xbd\xe7\x95\xa5\xe8\x8a\x82\xe7\x82\xb9";
|
||||
static const char STR_NUMBER_PICKER_ZH[] = "\xe6\x95\xb0\xe5\xad\x97\xe9\x80\x89\xe6\x8b\xa9";
|
||||
static const char STR_TEST_ANNOUNCE_ZH[] = "\xe6\xb5\x8b\xe8\xaf\x95\xe5\x85\xac\xe5\x91\x8a";
|
||||
static const char STR_NODE_ACTIONS_ZH[] = "\xe8\x8a\x82\xe7\x82\xb9\xe6\x93\x8d\xe4\xbd\x9c/\xe8\xae\xbe\xe7\xbd\xae";
|
||||
static const char STR_SHOW_NAME_LENGTH_ZH[] = "\xe6\x98\xbe\xe7\xa4\xba\xe9\x95\xbf/\xe7\x9f\xad\xe5\x90\x8d";
|
||||
static const char STR_BLUETOOTH_ZH[] = "\xe8\x93\x9d\xe7\x89\x99";
|
||||
static const char STR_NO_MESSAGES_ZH[] = "\xe6\x97\xa0\xe6\xb6\x88\xe6\x81\xaf";
|
||||
|
||||
inline const char *getStringZH(StringKey key)
|
||||
{
|
||||
switch (key) {
|
||||
case StringKey::Back:
|
||||
return STR_BACK_ZH;
|
||||
case StringKey::OK:
|
||||
return STR_OK_ZH;
|
||||
case StringKey::GotIt:
|
||||
return STR_GOT_IT_ZH;
|
||||
case StringKey::WelcomeToMeshtastic:
|
||||
return STR_WELCOME_TO_MESHTASTIC_ZH;
|
||||
case StringKey::SwipeToNavigate:
|
||||
return STR_SWIPE_TO_NAVIGATE_ZH;
|
||||
case StringKey::ClickToNavigate:
|
||||
return STR_CLICK_TO_NAVIGATE_ZH;
|
||||
case StringKey::UseSelectButton:
|
||||
return STR_USE_SELECT_BUTTON_ZH;
|
||||
case StringKey::DeviceRole:
|
||||
return STR_DEVICE_ROLE_ZH;
|
||||
case StringKey::RadioPreset:
|
||||
return STR_RADIO_PRESET_ZH;
|
||||
case StringKey::FrequencySlot:
|
||||
return STR_FREQUENCY_SLOT_ZH;
|
||||
case StringKey::LoRaRegion:
|
||||
return STR_LORA_REGION_ZH;
|
||||
case StringKey::Client:
|
||||
return STR_CLIENT_ZH;
|
||||
case StringKey::ClientMute:
|
||||
return STR_CLIENT_MUTE_ZH;
|
||||
case StringKey::LostAndFound:
|
||||
return STR_LOST_AND_FOUND_ZH;
|
||||
case StringKey::Tracker:
|
||||
return STR_TRACKER_ZH;
|
||||
case StringKey::Hour12:
|
||||
return STR_12HOUR_ZH;
|
||||
case StringKey::Hour24:
|
||||
return STR_24HOUR_ZH;
|
||||
case StringKey::ClockAction:
|
||||
return STR_CLOCK_ACTION_ZH;
|
||||
case StringKey::ClockFace:
|
||||
return STR_CLOCK_FACE_ZH;
|
||||
case StringKey::TimeFormat:
|
||||
return STR_TIME_FORMAT_ZH;
|
||||
case StringKey::Timezone:
|
||||
return STR_TIMEZONE_ZH;
|
||||
case StringKey::MessageAction:
|
||||
return STR_MESSAGE_ACTION_ZH;
|
||||
case StringKey::Reply:
|
||||
return STR_REPLY_ZH;
|
||||
case StringKey::ViewChats:
|
||||
return STR_VIEW_CHATS_ZH;
|
||||
case StringKey::UnmuteChannel:
|
||||
return STR_UNMUTE_CHANNEL_ZH;
|
||||
case StringKey::MuteChannel:
|
||||
return STR_MUTE_CHANNEL_ZH;
|
||||
case StringKey::Delete:
|
||||
return STR_DELETE_ZH;
|
||||
case StringKey::ReadAloud:
|
||||
return STR_READ_ALOUD_ZH;
|
||||
case StringKey::Brightness:
|
||||
return STR_BRIGHTNESS_ZH;
|
||||
case StringKey::FrameVisibility:
|
||||
return STR_FRAME_VISIBILITY_ZH;
|
||||
case StringKey::DisplayUnits:
|
||||
return STR_DISPLAY_UNITS_ZH;
|
||||
case StringKey::MessageBubbles:
|
||||
return STR_MESSAGE_BUBBLES_ZH;
|
||||
case StringKey::Theme:
|
||||
return STR_THEME_ZH;
|
||||
case StringKey::Reboot:
|
||||
return STR_REBOOT_ZH;
|
||||
case StringKey::Shutdown:
|
||||
return STR_SHUTDOWN_ZH;
|
||||
case StringKey::SwitchToMUI:
|
||||
return STR_SWITCH_TO_MUI_ZH;
|
||||
case StringKey::DisplayOptions:
|
||||
return STR_DISPLAY_OPTIONS_ZH;
|
||||
case StringKey::Language:
|
||||
return STR_LANGUAGE_ZH;
|
||||
case StringKey::Chinese:
|
||||
return STR_CHINESE_ZH;
|
||||
case StringKey::English:
|
||||
return STR_ENGLISH_ZH;
|
||||
case StringKey::NoGPS:
|
||||
return STR_NO_GPS_ZH;
|
||||
case StringKey::GPSoff:
|
||||
return STR_GPS_OFF_ZH;
|
||||
case StringKey::GPSnotPresent:
|
||||
return STR_GPS_NOT_PRESENT_ZH;
|
||||
case StringKey::GPSisDisabled:
|
||||
return STR_GPS_IS_DISABLED_ZH;
|
||||
case StringKey::Node:
|
||||
return STR_NODE_ZH;
|
||||
case StringKey::Hop:
|
||||
return STR_HOP_ZH;
|
||||
case StringKey::USB:
|
||||
return STR_USB_ZH;
|
||||
case StringKey::BT_off:
|
||||
return STR_BT_OFF_ZH;
|
||||
case StringKey::WiFi:
|
||||
return STR_WIFI_ZH;
|
||||
case StringKey::WiFiNotConnected:
|
||||
return STR_WIFI_NOT_CONNECTED_ZH;
|
||||
case StringKey::WiFiConnected:
|
||||
return STR_WIFI_CONNECTED_ZH;
|
||||
case StringKey::SSID:
|
||||
return STR_SSID_ZH;
|
||||
case StringKey::LoRaInfo:
|
||||
return STR_LORA_INFO_ZH;
|
||||
case StringKey::LoRa:
|
||||
return STR_LORA_ZH;
|
||||
case StringKey::Role:
|
||||
return STR_ROLE_ZH;
|
||||
case StringKey::Freq:
|
||||
return STR_FREQ_ZH;
|
||||
case StringKey::ChUtil:
|
||||
return STR_CHUTIL_ZH;
|
||||
case StringKey::System:
|
||||
return STR_SYSTEM_ZH;
|
||||
case StringKey::Heap:
|
||||
return STR_HEAP_ZH;
|
||||
case StringKey::PSRAM:
|
||||
return STR_PSRAM_ZH;
|
||||
case StringKey::Flash:
|
||||
return STR_FLASH_ZH;
|
||||
case StringKey::SD:
|
||||
return STR_SD_ZH;
|
||||
case StringKey::Ver:
|
||||
return STR_VER_ZH;
|
||||
case StringKey::Up:
|
||||
return STR_UP_ZH;
|
||||
case StringKey::ClientApp:
|
||||
return STR_CLIENT_APP_ZH;
|
||||
case StringKey::NoConnected:
|
||||
return STR_NO_CONNECTED_ZH;
|
||||
case StringKey::LOCKED:
|
||||
return STR_LOCKED_ZH;
|
||||
case StringKey::ConnectToUnlock:
|
||||
return STR_CONNECT_TO_UNLOCK_ZH;
|
||||
case StringKey::Battery:
|
||||
return STR_BATTERY_ZH;
|
||||
case StringKey::Resuming:
|
||||
return STR_RESUMING_ZH;
|
||||
case StringKey::LastHeard:
|
||||
return STR_LAST_HEARD_ZH;
|
||||
case StringKey::HopsSig:
|
||||
return STR_HOPS_SIG_ZH;
|
||||
case StringKey::HopsSignal:
|
||||
return STR_HOPS_SIGNAL_ZH;
|
||||
case StringKey::Nodes:
|
||||
return STR_NODES_ZH;
|
||||
case StringKey::Distance:
|
||||
return STR_DISTANCE_ZH;
|
||||
case StringKey::Bearings:
|
||||
return STR_BEARINGS_ZH;
|
||||
case StringKey::CreatingSSLCert:
|
||||
return STR_CREATING_SSL_ZH;
|
||||
case StringKey::PleaseWait:
|
||||
return STR_PLEASE_WAIT_ZH;
|
||||
case StringKey::CriticalFault:
|
||||
return STR_CRITICAL_FAULT_ZH;
|
||||
case StringKey::ForHelpVisit:
|
||||
return STR_FOR_HELP_VISIT_ZH;
|
||||
case StringKey::Updating:
|
||||
return STR_UPDATING_ZH;
|
||||
case StringKey::PleaseBePatient:
|
||||
return STR_PLEASE_BE_PATIENT_ZH;
|
||||
case StringKey::RebootInProgress:
|
||||
return STR_REBOOT_IN_PROGRESS_ZH;
|
||||
case StringKey::PowerMenu:
|
||||
return STR_POWER_MENU_ZH;
|
||||
case StringKey::SystemMenu:
|
||||
return STR_SYSTEM_MENU_ZH;
|
||||
case StringKey::ScreenOptions:
|
||||
return STR_SCREEN_OPTIONS_ZH;
|
||||
case StringKey::WifiToggle:
|
||||
return STR_WIFI_TOGGLE_ZH;
|
||||
case StringKey::BluetoothToggle:
|
||||
return STR_BLUETOOTH_TOGGLE_ZH;
|
||||
case StringKey::NodeDbReset:
|
||||
return STR_NODE_DB_RESET_ZH;
|
||||
case StringKey::ManageNode:
|
||||
return STR_MANAGE_NODE_ZH;
|
||||
case StringKey::RemoveFavorite:
|
||||
return STR_REMOVE_FAVORITE_ZH;
|
||||
case StringKey::AddFavorite:
|
||||
return STR_ADD_FAVORITE_ZH;
|
||||
case StringKey::TestMenu:
|
||||
return STR_TEST_MENU_ZH;
|
||||
case StringKey::TraceRoute:
|
||||
return STR_TRACE_ROUTE_ZH;
|
||||
case StringKey::ThrottleMessage:
|
||||
return STR_THROTTLE_MSG_ZH;
|
||||
case StringKey::MessageViewMode:
|
||||
return STR_MSG_VIEW_MODE_ZH;
|
||||
case StringKey::DeleteMessages:
|
||||
return STR_DELETE_MESSAGES_ZH;
|
||||
case StringKey::NodeNameLength:
|
||||
return STR_NODE_NAME_LENGTH_ZH;
|
||||
case StringKey::GPSMenu:
|
||||
return STR_GPS_MENU_ZH;
|
||||
case StringKey::GPSToggle:
|
||||
return STR_GPS_TOGGLE_ZH;
|
||||
case StringKey::GPSFormat:
|
||||
return STR_GPS_FORMAT_ZH;
|
||||
case StringKey::GPSSmartPosition:
|
||||
return STR_GPS_SMART_POS_ZH;
|
||||
case StringKey::GPSUpdateInterval:
|
||||
return STR_GPS_UPDATE_INTERVAL_ZH;
|
||||
case StringKey::GPSPositionBroadcast:
|
||||
return STR_GPS_POS_BCAST_ZH;
|
||||
case StringKey::CompassNorth:
|
||||
return STR_COMPASS_NORTH_ZH;
|
||||
case StringKey::BuzzerMode:
|
||||
return STR_BUZZER_MODE_ZH;
|
||||
case StringKey::HamModeConfirm:
|
||||
return STR_HAM_MODE_ZH;
|
||||
case StringKey::LicensedToNormal:
|
||||
return STR_LICENSED_NORMAL_ZH;
|
||||
case StringKey::KeyVerification:
|
||||
return STR_KEY_VERIFY_ZH;
|
||||
case StringKey::RegionUnset:
|
||||
return STR_REGION_UNSET_ZH;
|
||||
case StringKey::SelectRegionMessage:
|
||||
return STR_SELECT_REGION_ZH;
|
||||
case StringKey::Rebooting:
|
||||
return STR_REBOOTING_ZH;
|
||||
case StringKey::LoRaActions:
|
||||
return STR_LORA_ACTIONS_ZH;
|
||||
case StringKey::Slot0:
|
||||
return STR_SLOT0_ZH;
|
||||
case StringKey::WithPreset:
|
||||
return STR_WITH_PRESET_ZH;
|
||||
case StringKey::WithFreetext:
|
||||
return STR_WITH_FREETEXT_ZH;
|
||||
case StringKey::DeleteOldest:
|
||||
return STR_DELETE_OLDEST_ZH;
|
||||
case StringKey::DeleteThisChat:
|
||||
return STR_DELETE_THIS_CHAT_ZH;
|
||||
case StringKey::DeleteAll:
|
||||
return STR_DELETE_ALL_ZH;
|
||||
case StringKey::DeleteAllChats:
|
||||
return STR_DELETE_ALL_CHATS_ZH;
|
||||
case StringKey::TemporarilyMute:
|
||||
return STR_TEMPORARILY_MUTE_ZH;
|
||||
case StringKey::Unmute:
|
||||
return STR_UNMUTE_ZH;
|
||||
case StringKey::ToggleBacklight:
|
||||
return STR_TOGGLE_BACKLIGHT_ZH;
|
||||
case StringKey::SleepScreen:
|
||||
return STR_SLEEP_SCREEN_ZH;
|
||||
case StringKey::SendPosition:
|
||||
return STR_SEND_POSITION_ZH;
|
||||
case StringKey::SendNodeInfo:
|
||||
return STR_SEND_NODE_INFO_ZH;
|
||||
case StringKey::NewPresetMsg:
|
||||
return STR_NEW_PRESET_MSG_ZH;
|
||||
case StringKey::NewFreetextMsg:
|
||||
return STR_NEW_FREETEXT_MSG_ZH;
|
||||
case StringKey::Notifications:
|
||||
return STR_NOTIFICATIONS_ZH;
|
||||
case StringKey::Power:
|
||||
return STR_POWER_ZH;
|
||||
case StringKey::RebootShutdown:
|
||||
return STR_REBOOT_SHUTDOWN_ZH;
|
||||
case StringKey::GoToChat:
|
||||
return STR_GO_TO_CHAT_ZH;
|
||||
case StringKey::NewPreset:
|
||||
return STR_NEW_PRESET_ZH;
|
||||
case StringKey::Favorite:
|
||||
return STR_FAVORITE_ZH;
|
||||
case StringKey::UnmuteNotifications:
|
||||
return STR_UNMUTE_NOTIFICATIONS_ZH;
|
||||
case StringKey::MuteNotifications:
|
||||
return STR_MUTE_NOTIFICATIONS_ZH;
|
||||
case StringKey::UnignoreNode:
|
||||
return STR_UNIGNORE_NODE_ZH;
|
||||
case StringKey::IgnoreNode:
|
||||
return STR_IGNORE_NODE_ZH;
|
||||
case StringKey::NumberPicker:
|
||||
return STR_NUMBER_PICKER_ZH;
|
||||
case StringKey::TestAnnounce:
|
||||
return STR_TEST_ANNOUNCE_ZH;
|
||||
case StringKey::NodeActionsSettings:
|
||||
return STR_NODE_ACTIONS_ZH;
|
||||
case StringKey::ShowNameLength:
|
||||
return STR_SHOW_NAME_LENGTH_ZH;
|
||||
case StringKey::Bluetooth:
|
||||
return STR_BLUETOOTH_ZH;
|
||||
case StringKey::NoMessages:
|
||||
return STR_NO_MESSAGES_ZH;
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace l10n
|
||||
} // namespace meshtastic
|
||||
@@ -1,97 +0,0 @@
|
||||
#include "HapticFeedback.h"
|
||||
|
||||
#ifdef HAPTIC_FEEDBACK_PIN
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef HAPTIC_FEEDBACK_ACTIVE_LOW
|
||||
#define HAPTIC_FEEDBACK_ON_STATE LOW
|
||||
#define HAPTIC_FEEDBACK_OFF_STATE HIGH
|
||||
#else
|
||||
#define HAPTIC_FEEDBACK_ON_STATE HIGH
|
||||
#define HAPTIC_FEEDBACK_OFF_STATE LOW
|
||||
#endif
|
||||
|
||||
HapticFeedback *hapticFeedback = nullptr;
|
||||
|
||||
void initHapticFeedback()
|
||||
{
|
||||
if (!hapticFeedback)
|
||||
hapticFeedback = new HapticFeedback();
|
||||
}
|
||||
|
||||
HapticFeedback::HapticFeedback() : concurrency::OSThread("Haptic")
|
||||
{
|
||||
pinMode(HAPTIC_FEEDBACK_PIN, OUTPUT);
|
||||
digitalWrite(HAPTIC_FEEDBACK_PIN, HAPTIC_FEEDBACK_OFF_STATE);
|
||||
}
|
||||
|
||||
void HapticFeedback::motorWrite(bool on)
|
||||
{
|
||||
digitalWrite(HAPTIC_FEEDBACK_PIN, on ? HAPTIC_FEEDBACK_ON_STATE : HAPTIC_FEEDBACK_OFF_STATE);
|
||||
}
|
||||
|
||||
void HapticFeedback::pulse(uint16_t durationMs)
|
||||
{
|
||||
motorWrite(true);
|
||||
pulseOffAt = millis() + durationMs;
|
||||
if (pulseOffAt == 0) // 0 is the "no pulse" sentinel
|
||||
pulseOffAt = 1;
|
||||
scheduleNext();
|
||||
}
|
||||
|
||||
void HapticFeedback::armDelayedPulse(uint16_t delayMs, uint16_t durationMs)
|
||||
{
|
||||
delayedPulseAt = millis() + delayMs;
|
||||
if (delayedPulseAt == 0)
|
||||
delayedPulseAt = 1;
|
||||
delayedPulseDuration = durationMs;
|
||||
scheduleNext();
|
||||
}
|
||||
|
||||
void HapticFeedback::cancelDelayedPulse()
|
||||
{
|
||||
delayedPulseAt = 0;
|
||||
}
|
||||
|
||||
void HapticFeedback::scheduleNext()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
uint32_t next = 0;
|
||||
if (pulseOffAt != 0)
|
||||
next = pulseOffAt;
|
||||
if (delayedPulseAt != 0 && (next == 0 || (int32_t)(delayedPulseAt - next) < 0))
|
||||
next = delayedPulseAt;
|
||||
if (next == 0)
|
||||
return;
|
||||
int32_t delay = (int32_t)(next - now);
|
||||
setIntervalFromNow(delay > 0 ? (unsigned long)delay : 0);
|
||||
}
|
||||
|
||||
int32_t HapticFeedback::runOnce()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
|
||||
if (pulseOffAt != 0 && (int32_t)(now - pulseOffAt) >= 0) {
|
||||
motorWrite(false);
|
||||
pulseOffAt = 0;
|
||||
}
|
||||
|
||||
if (delayedPulseAt != 0 && (int32_t)(now - delayedPulseAt) >= 0) {
|
||||
uint16_t dur = delayedPulseDuration;
|
||||
delayedPulseAt = 0;
|
||||
pulse(dur);
|
||||
}
|
||||
|
||||
uint32_t next = 0;
|
||||
if (pulseOffAt != 0)
|
||||
next = pulseOffAt;
|
||||
if (delayedPulseAt != 0 && (next == 0 || (int32_t)(delayedPulseAt - next) < 0))
|
||||
next = delayedPulseAt;
|
||||
if (next == 0)
|
||||
return 60 * 1000;
|
||||
int32_t delay = (int32_t)(next - now);
|
||||
return delay > 0 ? delay : 0;
|
||||
}
|
||||
|
||||
#endif // HAPTIC_FEEDBACK_PIN
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef HAPTIC_FEEDBACK_PIN
|
||||
|
||||
#include "concurrency/OSThread.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Non-blocking pulses on a GPIO vibration motor. HAPTIC_FEEDBACK_ACTIVE_LOW inverts polarity.
|
||||
class HapticFeedback : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
HapticFeedback();
|
||||
void pulse(uint16_t durationMs = 30);
|
||||
void armDelayedPulse(uint16_t delayMs, uint16_t durationMs = 30);
|
||||
void cancelDelayedPulse();
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
uint32_t pulseOffAt = 0;
|
||||
uint32_t delayedPulseAt = 0;
|
||||
uint16_t delayedPulseDuration = 0;
|
||||
|
||||
void motorWrite(bool on);
|
||||
// Reschedule to the soonest pending event so later arms don't clobber earlier wakes.
|
||||
void scheduleNext();
|
||||
};
|
||||
|
||||
extern HapticFeedback *hapticFeedback;
|
||||
void initHapticFeedback();
|
||||
|
||||
#endif // HAPTIC_FEEDBACK_PIN
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "PowerFSM.h" // needed for event trigger
|
||||
#include "configuration.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "input/HapticFeedback.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#ifdef MESHTASTIC_LOCKDOWN
|
||||
#include "security/LockdownDisplay.h"
|
||||
@@ -257,16 +256,6 @@ void InputBroker::Init()
|
||||
}
|
||||
touchBacklightActive = false;
|
||||
};
|
||||
#endif
|
||||
#if defined(HAPTIC_FEEDBACK_PIN)
|
||||
// Blip on touch, second blip when long-press fires (500 ms = touchConfig.longPressTime default).
|
||||
touchConfig.suppressLeadUpSound = true;
|
||||
initHapticFeedback();
|
||||
touchConfig.onPress = []() {
|
||||
hapticFeedback->pulse(80);
|
||||
hapticFeedback->armDelayedPulse(500, 80);
|
||||
};
|
||||
touchConfig.onRelease = []() { hapticFeedback->cancelDelayedPulse(); };
|
||||
#endif
|
||||
TouchButtonThread->initButton(touchConfig);
|
||||
#endif
|
||||
|
||||
+13
-16
@@ -1071,6 +1071,19 @@ void setup()
|
||||
digitalWrite(RF95_FAN_EN, LOW ^ 0);
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
|
||||
// Initialize Wifi
|
||||
#if HAS_WIFI
|
||||
initWifi();
|
||||
#endif
|
||||
|
||||
#if HAS_ETHERNET
|
||||
// Initialize Ethernet
|
||||
initEthernet();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
// Start web server thread.
|
||||
webServerThread = new WebServerThread();
|
||||
@@ -1108,22 +1121,6 @@ void setup()
|
||||
setCPUFast(false); // 80MHz is fine for our slow peripherals
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// Force BT init before WiFi so NimBLE gets clean heap
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
setBluetoothEnable(true);
|
||||
#endif
|
||||
// Initialize Wifi after PowerFSM so BT gets clean heap during init
|
||||
#if HAS_WIFI
|
||||
initWifi();
|
||||
#endif
|
||||
|
||||
#if HAS_ETHERNET
|
||||
// Initialize Ethernet
|
||||
initEthernet();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap());
|
||||
LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram());
|
||||
|
||||
@@ -1742,6 +1742,13 @@ void NodeDB::installDefaultDeviceState()
|
||||
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
|
||||
owner.has_is_unmessagable = true;
|
||||
owner.is_unmessagable = false;
|
||||
|
||||
#ifdef HAS_HAM_2M_ONLY
|
||||
// Ham-band-only hardware defaults to licensed operation. The user can still flip this off later
|
||||
// (e.g. a commercial operator on an adjacent allocation who wants to keep encryption on) — we
|
||||
// only set the default here, not on every boot.
|
||||
owner.is_licensed = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// We reserve a few nodenums for future use
|
||||
|
||||
+8
-31
@@ -40,17 +40,6 @@
|
||||
#include "Throttle.h"
|
||||
#include <RTC.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr uint8_t FILES_MANIFEST_LEVELS = 3;
|
||||
constexpr size_t FILES_MANIFEST_MAX_COUNT = 64;
|
||||
|
||||
void releaseFilesManifest(std::vector<meshtastic_FileInfo> &filesManifest)
|
||||
{
|
||||
std::vector<meshtastic_FileInfo>().swap(filesManifest);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Flag to indicate a heartbeat was received and we should send queue status
|
||||
bool heartbeatReceived = false;
|
||||
|
||||
@@ -309,31 +298,18 @@ void PhoneAPI::handleStartConfig()
|
||||
state = STATE_SEND_MY_INFO;
|
||||
}
|
||||
pauseBluetoothLogging = true;
|
||||
spiLock->lock();
|
||||
#if defined(MESHTASTIC_EXCLUDE_FILES_MANIFEST)
|
||||
// Skip the recursive FS walk. Used by platforms whose Zephyr LittleFS
|
||||
// backend can't safely traverse a deep tree (e.g. nRF54L15) and platforms
|
||||
// that don't support OTA browsing — the manifest is only consumed by
|
||||
// companion apps for those flows.
|
||||
releaseFilesManifest(filesManifest);
|
||||
filesManifest.clear();
|
||||
#else
|
||||
// Manifest is never read on the node-info-only path (STATE_SEND_FILEMANIFEST
|
||||
// short-circuits to sendConfigComplete), so skip the SPI lock + FS walk.
|
||||
if (config_nonce != SPECIAL_NONCE_ONLY_NODES) {
|
||||
bool filesManifestLimited = false;
|
||||
{
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
filesManifest = getFiles("/", FILES_MANIFEST_LEVELS, FILES_MANIFEST_MAX_COUNT, &filesManifestLimited);
|
||||
}
|
||||
if (filesManifestLimited) {
|
||||
LOG_WARN("Got %zu files in manifest (limited to %zu entries/depth %u)", filesManifest.size(),
|
||||
FILES_MANIFEST_MAX_COUNT, static_cast<unsigned>(FILES_MANIFEST_LEVELS));
|
||||
} else {
|
||||
LOG_DEBUG("Got %zu files in manifest", filesManifest.size());
|
||||
}
|
||||
} else {
|
||||
releaseFilesManifest(filesManifest);
|
||||
}
|
||||
filesManifest = getFiles("/", 10);
|
||||
#endif
|
||||
spiLock->unlock();
|
||||
LOG_DEBUG("Got %d files in manifest", filesManifest.size());
|
||||
|
||||
LOG_INFO("Start API client config millis=%u", millis());
|
||||
// Protect against concurrent BLE callbacks: they run in NimBLE's FreeRTOS task and also touch nodeInfoQueue.
|
||||
@@ -401,7 +377,8 @@ void PhoneAPI::close()
|
||||
replayPhase = REPLAY_PHASE_IDLE;
|
||||
}
|
||||
packetForPhone = NULL;
|
||||
releaseFilesManifest(filesManifest);
|
||||
filesManifest.clear();
|
||||
filesManifest.shrink_to_fit();
|
||||
lastPortNumToRadio.clear();
|
||||
fromRadioNum = 0;
|
||||
config_nonce = 0;
|
||||
@@ -966,7 +943,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
// ONLY_NODES variants skip the manifest.
|
||||
if (config_state == filesManifest.size() || config_nonce == SPECIAL_NONCE_ONLY_NODES) {
|
||||
config_state = 0;
|
||||
releaseFilesManifest(filesManifest);
|
||||
filesManifest.clear();
|
||||
// Skip to complete packet
|
||||
sendConfigComplete();
|
||||
} else {
|
||||
|
||||
@@ -113,6 +113,11 @@ void RF95Interface::setTransmitEnable(bool txon)
|
||||
/// \return true if initialisation succeeded.
|
||||
bool RF95Interface::init()
|
||||
{
|
||||
#ifdef RF95_POWER_EN
|
||||
pinMode(RF95_POWER_EN, OUTPUT);
|
||||
digitalWrite(RF95_POWER_EN, HIGH);
|
||||
#endif
|
||||
|
||||
RadioLibInterface::init();
|
||||
|
||||
#if defined(RADIOMASTER_900_BANDIT_NANO) || defined(RADIOMASTER_900_BANDIT)
|
||||
@@ -335,6 +340,10 @@ bool RF95Interface::sleep()
|
||||
setStandby(); // First cancel any active receiving/sending
|
||||
lora->sleep();
|
||||
|
||||
#ifdef RF95_POWER_EN
|
||||
digitalWrite(RF95_POWER_EN, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef RF95_FAN_EN
|
||||
digitalWrite(RF95_FAN_EN, 0);
|
||||
#endif
|
||||
|
||||
+27
-30
@@ -52,8 +52,7 @@ void StreamAPI::writeStream()
|
||||
do {
|
||||
// Send every packet we can
|
||||
len = getFromRadio(txBuf + HEADER_LEN);
|
||||
if (len != 0 && !emitTxBuffer(len))
|
||||
break;
|
||||
emitTxBuffer(len);
|
||||
} while (len);
|
||||
}
|
||||
}
|
||||
@@ -170,36 +169,21 @@ int32_t StreamAPI::readStream()
|
||||
/**
|
||||
* Send the current txBuffer over our stream
|
||||
*/
|
||||
bool StreamAPI::writeFrame(uint8_t *buf, size_t len)
|
||||
void StreamAPI::emitTxBuffer(size_t len)
|
||||
{
|
||||
if (len == 0 || !canWrite)
|
||||
return false;
|
||||
if (len != 0) {
|
||||
txBuf[0] = START1;
|
||||
txBuf[1] = START2;
|
||||
txBuf[2] = (len >> 8) & 0xff;
|
||||
txBuf[3] = len & 0xff;
|
||||
|
||||
buf[0] = START1;
|
||||
buf[1] = START2;
|
||||
buf[2] = (len >> 8) & 0xff;
|
||||
buf[3] = len & 0xff;
|
||||
|
||||
auto totalLen = len + HEADER_LEN;
|
||||
// Serialize write-readiness checks, writes and write-failure handling
|
||||
// against concurrent stream writes/close.
|
||||
concurrency::LockGuard guard(&streamLock);
|
||||
if (!canWriteFrame(totalLen))
|
||||
return false;
|
||||
|
||||
size_t written = stream->write(buf, totalLen);
|
||||
if (written == totalLen) {
|
||||
auto totalLen = len + HEADER_LEN;
|
||||
// Serialize stream writes against `emitLogRecord` so a LOG_ firing
|
||||
// mid-packet-emission can't interleave bytes on the wire.
|
||||
concurrency::LockGuard guard(&streamLock);
|
||||
stream->write(txBuf, totalLen);
|
||||
stream->flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
onFrameWriteFailed(totalLen, written);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StreamAPI::emitTxBuffer(size_t len)
|
||||
{
|
||||
return writeFrame(txBuf, len);
|
||||
}
|
||||
|
||||
void StreamAPI::emitRebooted()
|
||||
@@ -237,7 +221,20 @@ void StreamAPI::emitLogRecord(meshtastic_LogRecord_Level level, const char *src,
|
||||
|
||||
size_t len =
|
||||
pb_encode_to_bytes(txBufLog + HEADER_LEN, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratchLog);
|
||||
writeFrame(txBufLog, len);
|
||||
if (len != 0) {
|
||||
txBufLog[0] = START1;
|
||||
txBufLog[1] = START2;
|
||||
txBufLog[2] = (len >> 8) & 0xff;
|
||||
txBufLog[3] = len & 0xff;
|
||||
|
||||
auto totalLen = len + HEADER_LEN;
|
||||
// Serialize stream writes against `emitTxBuffer` so a packet
|
||||
// emission in flight on another task doesn't interleave bytes
|
||||
// with this log record.
|
||||
concurrency::LockGuard guard(&streamLock);
|
||||
stream->write(txBufLog, totalLen);
|
||||
stream->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/// Hookable to find out when connection changes
|
||||
@@ -252,4 +249,4 @@ void StreamAPI::onConnectionChanged(bool connected)
|
||||
// received a packet in a while
|
||||
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class StreamAPI : public PhoneAPI
|
||||
/**
|
||||
* Send the current txBuffer over our stream
|
||||
*/
|
||||
bool emitTxBuffer(size_t len);
|
||||
void emitTxBuffer(size_t len);
|
||||
|
||||
/// Are we allowed to write packets to our output stream (subclasses can turn this off - i.e. SerialConsole)
|
||||
bool canWrite = true;
|
||||
@@ -91,12 +91,7 @@ class StreamAPI : public PhoneAPI
|
||||
/// Low level function to emit a protobuf encapsulated log record
|
||||
void emitLogRecord(meshtastic_LogRecord_Level level, const char *src, const char *format, va_list arg);
|
||||
|
||||
virtual bool canWriteFrame(size_t frameLen) { return true; }
|
||||
virtual void onFrameWriteFailed(size_t frameLen, size_t writtenLen) {}
|
||||
|
||||
private:
|
||||
bool writeFrame(uint8_t *buf, size_t len);
|
||||
|
||||
/// Dedicated scratch + tx buffer for LogRecord emission.
|
||||
///
|
||||
/// The main packet emission path (`writeStream` -> `getFromRadio` ->
|
||||
@@ -118,4 +113,4 @@ class StreamAPI : public PhoneAPI
|
||||
meshtastic_FromRadio fromRadioScratchLog = {};
|
||||
uint8_t txBufLog[MAX_STREAM_BUF_SIZE] = {0};
|
||||
concurrency::Lock streamLock;
|
||||
};
|
||||
};
|
||||
@@ -22,38 +22,12 @@ template <typename T> void ServerAPI<T>::close()
|
||||
StreamAPI::close();
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently
|
||||
/// connected
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
template <typename T> bool ServerAPI<T>::checkIsConnected()
|
||||
{
|
||||
return client.connected();
|
||||
}
|
||||
|
||||
template <typename T> bool ServerAPI<T>::canWriteFrame(size_t)
|
||||
{
|
||||
// Only a dropped link is a reason to refuse a write up front. A full transmit
|
||||
// buffer (availableForWrite() == 0) is normal backpressure, not a dead socket,
|
||||
// so we must not close the connection on it. A genuinely failed write is
|
||||
// detected after the fact in onFrameWriteFailed().
|
||||
if (!client.connected()) {
|
||||
canWrite = false;
|
||||
enabled = false;
|
||||
LOG_WARN("TCP client disconnected before write, closing API service");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> void ServerAPI<T>::onFrameWriteFailed(size_t frameLen, size_t writtenLen)
|
||||
{
|
||||
canWrite = false;
|
||||
enabled = false;
|
||||
LOG_WARN("TCP client write short (%lu/%lu bytes), closing API service", (unsigned long)writtenLen, (unsigned long)frameLen);
|
||||
close();
|
||||
}
|
||||
|
||||
template <class T> int32_t ServerAPI<T>::runOnce()
|
||||
{
|
||||
if (client.connected()) {
|
||||
@@ -121,4 +95,4 @@ template <class T, class U> int32_t APIServerPort<T, U>::runOnce()
|
||||
waitTime = 100;
|
||||
#endif
|
||||
return 100; // only check occasionally for incoming connections
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,6 @@ template <class T> class ServerAPI : public StreamAPI, private concurrency::OSTh
|
||||
/// We override this method to prevent publishing EVENT_SERIAL_CONNECTED/DISCONNECTED for wifi links (we want the board to
|
||||
/// stay in the POWERED state to prevent disabling wifi)
|
||||
virtual void onConnectionChanged(bool connected) override {}
|
||||
virtual bool canWriteFrame(size_t frameLen) override;
|
||||
virtual void onFrameWriteFailed(size_t frameLen, size_t writtenLen) override;
|
||||
|
||||
virtual int32_t runOnce() override; // Check for dropped client connections
|
||||
};
|
||||
|
||||
@@ -198,6 +198,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
|
||||
#elif defined(T_BEAM_1W)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_TBEAM_1_WATT
|
||||
#elif defined(T_BEAM_BPF)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_TBEAM_BPF
|
||||
#elif defined(T_LORA_PAGER)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER
|
||||
#elif defined(HELTEC_V4)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Free up some precious space in the iram0_0_seg memory segment
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <esp_attr.h>
|
||||
#include <esp_flash.h>
|
||||
#include <spi_flash_chip_driver.h>
|
||||
|
||||
#define IRAM_SECTION section(".iram1.stub")
|
||||
|
||||
IRAM_ATTR esp_err_t stub_probe(esp_flash_t *chip, uint32_t flash_id)
|
||||
{
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
const spi_flash_chip_t stub_flash_chip __attribute__((IRAM_SECTION)) = {
|
||||
.name = "stub",
|
||||
.probe = stub_probe,
|
||||
};
|
||||
|
||||
extern const spi_flash_chip_t __wrap_esp_flash_chip_gd __attribute__((IRAM_SECTION, alias("stub_flash_chip")));
|
||||
extern const spi_flash_chip_t __wrap_esp_flash_chip_issi __attribute__((IRAM_SECTION, alias("stub_flash_chip")));
|
||||
extern const spi_flash_chip_t __wrap_esp_flash_chip_winbond __attribute__((IRAM_SECTION, alias("stub_flash_chip")));
|
||||
@@ -33,7 +33,13 @@ void variant_shutdown() {}
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
void setBluetoothEnable(bool enable)
|
||||
{
|
||||
#if defined(USE_WS5500) || defined(USE_CH390D)
|
||||
if ((config.bluetooth.enabled == true) && (config.network.wifi_enabled == false))
|
||||
#elif HAS_WIFI
|
||||
if (!isWifiAvailable() && config.bluetooth.enabled == true)
|
||||
#else
|
||||
if (config.bluetooth.enabled == true)
|
||||
#endif
|
||||
{
|
||||
if (!nimbleBluetooth) {
|
||||
nimbleBluetooth = new NimbleBluetooth();
|
||||
@@ -42,6 +48,9 @@ void setBluetoothEnable(bool enable)
|
||||
powerMon->setState(meshtastic_PowerMon_State_BT_On);
|
||||
nimbleBluetooth->setup();
|
||||
}
|
||||
// For ESP32, no way to recover from bluetooth shutdown without reboot
|
||||
// BLE advertising automatically stops when MCU enters light-sleep(?)
|
||||
// For deep-sleep, shutdown hardware with nimbleBluetooth->deinit(). Requires reboot to reverse
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -89,8 +89,6 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_CARD
|
||||
#elif defined(TTGO_T_ECHO_PLUS)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_PLUS
|
||||
#elif defined(T_IMPULSE_PLUS)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_T_IMPULSE_PLUS
|
||||
#elif defined(ELECROW_ThinkNode_M1)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
|
||||
#elif defined(ELECROW_ThinkNode_M3)
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
#include "SGM41562.h"
|
||||
|
||||
#ifdef HAS_SGM41562
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
SGM41562 *sgm41562 = nullptr;
|
||||
|
||||
bool initSGM41562(TwoWire &wire)
|
||||
{
|
||||
if (sgm41562)
|
||||
return true;
|
||||
sgm41562 = new SGM41562();
|
||||
if (!sgm41562->begin(wire)) {
|
||||
delete sgm41562;
|
||||
sgm41562 = nullptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SGM41562::readReg(uint8_t reg, uint8_t &value)
|
||||
{
|
||||
wire_->beginTransmission(address_);
|
||||
wire_->write(reg);
|
||||
if (wire_->endTransmission(false) != 0)
|
||||
return false;
|
||||
if (wire_->requestFrom((int)address_, 1) != 1)
|
||||
return false;
|
||||
value = wire_->read();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SGM41562::writeReg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
wire_->beginTransmission(address_);
|
||||
wire_->write(reg);
|
||||
wire_->write(value);
|
||||
return wire_->endTransmission() == 0;
|
||||
}
|
||||
|
||||
bool SGM41562::updateReg(uint8_t reg, uint8_t mask, uint8_t value)
|
||||
{
|
||||
uint8_t cur;
|
||||
if (!readReg(reg, cur))
|
||||
return false;
|
||||
cur = (cur & ~mask) | (value & mask);
|
||||
return writeReg(reg, cur);
|
||||
}
|
||||
|
||||
bool SGM41562::begin(TwoWire &wire, uint8_t address)
|
||||
{
|
||||
wire_ = &wire;
|
||||
address_ = address;
|
||||
|
||||
uint8_t id;
|
||||
if (!readReg(REG_DEVICE_ID, id)) {
|
||||
LOG_WARN("SGM41562: I2C read failed at 0x%02X", address_);
|
||||
return false;
|
||||
}
|
||||
if (id != DEVICE_ID_EXPECTED) {
|
||||
LOG_WARN("SGM41562: unexpected device ID 0x%02X (expected 0x%02X)", id, DEVICE_ID_EXPECTED);
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("SGM41562: detected at 0x%02X (id 0x%02X)", address_, id);
|
||||
|
||||
// Mirror the vendor reference init sequence: PCB OTP off, NTC off,
|
||||
// watchdog off, charger enabled. These match LilyGo's stock firmware
|
||||
// for the T-Impulse Plus.
|
||||
delay(120);
|
||||
writeReg(REG_SYS_VOLTAGE_REG, 0xB7);
|
||||
writeReg(REG_MISC_OP_CONTROL, 0x40);
|
||||
writeReg(REG_CHARGE_TERM_TIMER, 0x1A);
|
||||
writeReg(REG_POWER_ON_CFG, 0xA4);
|
||||
|
||||
return refresh();
|
||||
}
|
||||
|
||||
bool SGM41562::refresh()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
if (lastRefreshMs_ != 0 && (now - lastRefreshMs_) < 250)
|
||||
return true; // cached
|
||||
lastRefreshMs_ = now == 0 ? 1 : now;
|
||||
|
||||
uint8_t status, fault;
|
||||
if (!readReg(REG_SYSTEM_STATUS, status))
|
||||
return false;
|
||||
if (!readReg(REG_FAULT, fault))
|
||||
return false;
|
||||
|
||||
chargeStatus_ = static_cast<ChargeStatus>((status >> SYS_STATUS_CHRG_SHIFT) & SYS_STATUS_CHRG_MASK);
|
||||
inputPowerGood_ = (status & SYS_STATUS_PG) != 0;
|
||||
thermalReg_ = (status & SYS_STATUS_THERM_REG) != 0;
|
||||
faultMask_ = fault & 0x3F; // bits [7:6] are enter_ship_time config, not faults
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SGM41562::setChargeEnable(bool enable)
|
||||
{
|
||||
return updateReg(REG_POWER_ON_CFG, POWER_ON_CFG_CHG_DISABLE, enable ? 0x00 : POWER_ON_CFG_CHG_DISABLE);
|
||||
}
|
||||
|
||||
bool SGM41562::setShippingModeEnable(bool enable)
|
||||
{
|
||||
return updateReg(REG_MISC_OP_CONTROL, MISC_OP_SHIPPING_MODE, enable ? MISC_OP_SHIPPING_MODE : 0x00);
|
||||
}
|
||||
|
||||
#endif // HAS_SGM41562
|
||||
@@ -1,102 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef HAS_SGM41562
|
||||
|
||||
#include <Wire.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// SG Micro SGM41562 — single-cell Li-ion buck charger, I²C-controlled, no
|
||||
// fuel gauge. This driver exposes status (charging / input good / fault),
|
||||
// charge enable, and shipping-mode control. Battery voltage/percent still
|
||||
// come from the platform ADC path; the charger is plumbed in as a
|
||||
// side-channel for isCharging()/isVbusIn() in AnalogBatteryLevel.
|
||||
//
|
||||
// Reference: SGM41562 datasheet (Cmd map + bit fields cross-verified against
|
||||
// LilyGo's `Cpp_Bus_Driver::Sgm41562xx` driver, which is what their vendor
|
||||
// example for this board uses).
|
||||
|
||||
#ifndef SGM41562_ADDR
|
||||
#define SGM41562_ADDR 0x03 // Per datasheet — unusual but correct
|
||||
#endif
|
||||
|
||||
#ifndef SGM41562_WIRE
|
||||
#define SGM41562_WIRE Wire1 // Most boards put the PMU on the secondary bus
|
||||
#endif
|
||||
|
||||
class SGM41562
|
||||
{
|
||||
public:
|
||||
enum class ChargeStatus : uint8_t {
|
||||
NotCharging = 0b00,
|
||||
Precharge = 0b01,
|
||||
FastCharge = 0b10,
|
||||
ChargeDone = 0b11,
|
||||
};
|
||||
|
||||
bool begin(TwoWire &wire, uint8_t address = SGM41562_ADDR);
|
||||
|
||||
// Re-read the system status + fault registers. Throttled internally to
|
||||
// at most one I²C transaction per 250 ms — call as often as you like.
|
||||
bool refresh();
|
||||
|
||||
// Status — cached from the most recent refresh().
|
||||
ChargeStatus chargeStatus() const { return chargeStatus_; }
|
||||
bool isCharging() const { return chargeStatus_ == ChargeStatus::Precharge || chargeStatus_ == ChargeStatus::FastCharge; }
|
||||
bool isChargeDone() const { return chargeStatus_ == ChargeStatus::ChargeDone; }
|
||||
bool isInputPowerGood() const { return inputPowerGood_; }
|
||||
bool isThermalRegulation() const { return thermalReg_; }
|
||||
uint8_t faultMask() const { return faultMask_; }
|
||||
|
||||
// Control.
|
||||
bool setChargeEnable(bool enable);
|
||||
bool setShippingModeEnable(bool enable);
|
||||
|
||||
private:
|
||||
TwoWire *wire_ = nullptr;
|
||||
uint8_t address_ = SGM41562_ADDR;
|
||||
uint32_t lastRefreshMs_ = 0;
|
||||
|
||||
ChargeStatus chargeStatus_ = ChargeStatus::NotCharging;
|
||||
bool inputPowerGood_ = false;
|
||||
bool thermalReg_ = false;
|
||||
uint8_t faultMask_ = 0;
|
||||
|
||||
bool readReg(uint8_t reg, uint8_t &value);
|
||||
bool writeReg(uint8_t reg, uint8_t value);
|
||||
bool updateReg(uint8_t reg, uint8_t mask, uint8_t value);
|
||||
|
||||
// SGM41562 register addresses
|
||||
static constexpr uint8_t REG_INPUT_SOURCE = 0x00;
|
||||
static constexpr uint8_t REG_POWER_ON_CFG = 0x01;
|
||||
static constexpr uint8_t REG_CHARGE_CURRENT = 0x02;
|
||||
static constexpr uint8_t REG_DISCHARGE_TERM_CURRENT = 0x03;
|
||||
static constexpr uint8_t REG_CHARGE_VOLTAGE = 0x04;
|
||||
static constexpr uint8_t REG_CHARGE_TERM_TIMER = 0x05;
|
||||
static constexpr uint8_t REG_MISC_OP_CONTROL = 0x06;
|
||||
static constexpr uint8_t REG_SYS_VOLTAGE_REG = 0x07;
|
||||
static constexpr uint8_t REG_SYSTEM_STATUS = 0x08;
|
||||
static constexpr uint8_t REG_FAULT = 0x09;
|
||||
static constexpr uint8_t REG_I2C_ADDR_MISC = 0x0A;
|
||||
static constexpr uint8_t REG_DEVICE_ID = 0x0B;
|
||||
|
||||
// Bit positions in REG_POWER_ON_CFG.
|
||||
static constexpr uint8_t POWER_ON_CFG_CHG_DISABLE = 0x08; // bit 3: 1 = charging disabled
|
||||
// Bit positions in REG_MISC_OP_CONTROL.
|
||||
static constexpr uint8_t MISC_OP_SHIPPING_MODE = 0x20; // bit 5: 1 = enter shipping mode
|
||||
// Bit positions in REG_SYSTEM_STATUS.
|
||||
static constexpr uint8_t SYS_STATUS_CHRG_SHIFT = 3;
|
||||
static constexpr uint8_t SYS_STATUS_CHRG_MASK = 0x03;
|
||||
static constexpr uint8_t SYS_STATUS_PG = 0x02; // bit 1: input power good
|
||||
static constexpr uint8_t SYS_STATUS_THERM_REG = 0x01; // bit 0: thermal regulation
|
||||
|
||||
static constexpr uint8_t DEVICE_ID_EXPECTED = 0x04;
|
||||
};
|
||||
|
||||
extern SGM41562 *sgm41562;
|
||||
|
||||
// Lazy-instantiate the global on the supplied wire. Returns true on success.
|
||||
bool initSGM41562(TwoWire &wire);
|
||||
|
||||
#endif // HAS_SGM41562
|
||||
@@ -1,82 +0,0 @@
|
||||
#include "TestUtil.h"
|
||||
#include "gps/RTC.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unity.h>
|
||||
|
||||
// Regression coverage for issue #9828: on boards without a hardware RTC (e.g. RP2040),
|
||||
// gettimeofday() can return uptime seconds rather than wall-clock time. A later readFromRTC()
|
||||
// must not overwrite a higher-quality network/GPS time with that value, but it should still seed
|
||||
// the clock when nothing better exists yet.
|
||||
//
|
||||
// The native test build compiles the RV3028 hardware-RTC branch (variants/native/portduino
|
||||
// defines RV3028_RTC), so these tests use setReadFromRTCUseSystemTimeForTests() to force the
|
||||
// no-hardware-RTC fallback path and setRTCSystemTimeForTests() to inject a deterministic clock.
|
||||
|
||||
static const uint32_t kAllowedDriftSeconds = 2;
|
||||
static const time_t kUptimeSeconds = 21; // what gettimeofday() returns on RP2040 without a real clock
|
||||
|
||||
// A clearly-valid wall-clock epoch, safely inside any BUILD_EPOCH validity window.
|
||||
static time_t makeValidEpoch()
|
||||
{
|
||||
return time(NULL) + SEC_PER_DAY;
|
||||
}
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
resetRTCStateForTests();
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
resetRTCStateForTests();
|
||||
}
|
||||
|
||||
// A higher-quality network time must survive a later system-time read that only knows uptime.
|
||||
static void test_readFromRTC_preserves_better_network_time(void)
|
||||
{
|
||||
const time_t networkEpoch = makeValidEpoch();
|
||||
struct timeval networkTime;
|
||||
networkTime.tv_sec = networkEpoch;
|
||||
networkTime.tv_usec = 0;
|
||||
TEST_ASSERT_EQUAL_INT(RTCSetResultSuccess, perhapsSetRTC(RTCQualityFromNet, &networkTime));
|
||||
|
||||
// Simulate a later readFromRTC() falling back to a system clock that only knows uptime.
|
||||
struct timeval uptime;
|
||||
uptime.tv_sec = kUptimeSeconds;
|
||||
uptime.tv_usec = 0;
|
||||
setRTCSystemTimeForTests(&uptime);
|
||||
setReadFromRTCUseSystemTimeForTests(true);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(RTCSetResultSuccess, readFromRTC());
|
||||
TEST_ASSERT_EQUAL_INT(RTCQualityFromNet, getRTCQuality());
|
||||
TEST_ASSERT_UINT32_WITHIN(kAllowedDriftSeconds, (uint32_t)networkEpoch, getValidTime(RTCQualityFromNet));
|
||||
}
|
||||
|
||||
// Before any higher-quality source exists, the fallback should still seed the clock.
|
||||
static void test_readFromRTC_initializes_time_when_no_better_source(void)
|
||||
{
|
||||
const time_t systemEpoch = makeValidEpoch();
|
||||
struct timeval systemTime;
|
||||
systemTime.tv_sec = systemEpoch;
|
||||
systemTime.tv_usec = 0;
|
||||
setRTCSystemTimeForTests(&systemTime);
|
||||
setReadFromRTCUseSystemTimeForTests(true);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(RTCSetResultSuccess, readFromRTC());
|
||||
TEST_ASSERT_EQUAL_INT(RTCQualityNone, getRTCQuality());
|
||||
TEST_ASSERT_UINT32_WITHIN(kAllowedDriftSeconds, (uint32_t)systemEpoch, getTime());
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(10);
|
||||
initializeTestEnvironment();
|
||||
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_readFromRTC_preserves_better_network_time);
|
||||
RUN_TEST(test_readFromRTC_initializes_time_when_no_better_source);
|
||||
exit(UNITY_END());
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -1,24 +0,0 @@
|
||||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t TX = 21;
|
||||
static const uint8_t RX = 20;
|
||||
|
||||
static const uint8_t SDA = 12;
|
||||
static const uint8_t SCL = 13;
|
||||
|
||||
static const uint8_t SS = 8;
|
||||
static const uint8_t MOSI = 7;
|
||||
static const uint8_t MISO = 6;
|
||||
static const uint8_t SCK = 10;
|
||||
|
||||
static const uint8_t A0 = 0;
|
||||
static const uint8_t A1 = 1;
|
||||
static const uint8_t A2 = 2;
|
||||
static const uint8_t A3 = 3;
|
||||
static const uint8_t A4 = 4;
|
||||
static const uint8_t A5 = 5;
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
||||
@@ -1,29 +0,0 @@
|
||||
; ESP32 C3 Super Mini Development Board
|
||||
; https://www.espboards.dev/esp32/esp32-c3-super-mini/
|
||||
[env:esp32c3_moonshine]
|
||||
|
||||
extends = esp32c3_base
|
||||
board = esp32-c3-devkitm-1
|
||||
board_level = pr
|
||||
build_flags =
|
||||
${esp32c3_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-I variants/esp32c3/diy/esp32c3_moonshine
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
monitor_speed = 115200
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyUSB0
|
||||
upload_speed = 921600
|
||||
|
||||
|
||||
; ------------------- Flash 核心配置 -------------------
|
||||
; 1. Flash 容量(根据硬件实际值改,常见 4MB/8MB)
|
||||
board_build.flash_size = 4MB
|
||||
; 2. Flash 模式(ESP32-C3 推荐 dio)
|
||||
board_build.flash_mode = dio
|
||||
; 3. Flash 时钟频率(ESP32-C3 推荐 80MHz)
|
||||
board_build.flash_freq = 80MHz
|
||||
|
||||
; (可选)上传时的 Flash 配置(和上面保持一致即可)
|
||||
board_upload.flash_size = 4MB
|
||||
@@ -1,63 +0,0 @@
|
||||
#define BUTTON_PIN 9
|
||||
|
||||
#define HAS_SCREEN 0
|
||||
|
||||
#define HAS_I2C 0
|
||||
#define WIRE_INTERFACES_COUNT (0)
|
||||
#define I2C_SDA 12
|
||||
#define I2C_SCL 13
|
||||
|
||||
|
||||
#define BATTERY_PIN 1
|
||||
#define ADC_CHANNEL ADC_CHANNEL_1
|
||||
#define ADC_MULTIPLIER 2.0f
|
||||
|
||||
#define LED_POWER 0 // LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
|
||||
#define HAS_GPS 0
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
|
||||
//#define E220_400M30S
|
||||
//#define E220_400M33S
|
||||
#define E22_400M33S
|
||||
|
||||
#ifdef E220_400M30S
|
||||
#define SETTING_MAX_POWER 30
|
||||
#define TX_GAIN_LORA 8
|
||||
#define SX126X_MAX_POWER 22
|
||||
#endif
|
||||
|
||||
#ifdef E22_400M33S
|
||||
#define SETTING_MAX_POWER 22
|
||||
#define NUM_PA_POINTS 1
|
||||
#define TX_GAIN_LORA 0
|
||||
#define SX126X_MAX_POWER 22
|
||||
//#define HAS_LORA_FEM 1
|
||||
#endif
|
||||
|
||||
#define USE_LLCC68
|
||||
#define USE_SX1262
|
||||
#define USE_SX1268
|
||||
|
||||
#define LORA_SCK 10
|
||||
#define LORA_MISO 6
|
||||
#define LORA_MOSI 7
|
||||
#define LORA_CS 8
|
||||
#define LORA_DIO0 RADIOLIB_NC
|
||||
#define LORA_RESET 5
|
||||
#define LORA_DIO1 3
|
||||
#define LORA_DIO2 RADIOLIB_NC
|
||||
#define LORA_BUSY 4
|
||||
|
||||
#define SX126X_RXEN 2
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_BUSY
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
#define TCXO_OPTIONAL
|
||||
@@ -37,9 +37,6 @@ extends = env:picomputer-s3
|
||||
build_flags =
|
||||
${env:picomputer-s3.build_flags}
|
||||
-D MESHTASTIC_EXCLUDE_WEBSERVER=1
|
||||
; device-ui's I2CKeyboardScanner unconditionally calls Wire.begin(I2C_SDA, I2C_SCL);
|
||||
-D I2C_SDA=8
|
||||
-D I2C_SCL=9
|
||||
-D INPUTDRIVER_MATRIX_TYPE=1
|
||||
-D USE_PIN_BUZZER=PIN_BUZZER
|
||||
-D USE_SX127x
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USB_VID 0x303a
|
||||
#define USB_PID 0x1001
|
||||
|
||||
// UART1 (qwiic)
|
||||
static const uint8_t TX = 43;
|
||||
static const uint8_t RX = 44;
|
||||
|
||||
// I2C for OLED and sensors
|
||||
static const uint8_t SDA = 8;
|
||||
static const uint8_t SCL = 9;
|
||||
|
||||
// Default SPI mapped to Radio/SD
|
||||
static const uint8_t SS = 1; // LoRa CS
|
||||
static const uint8_t MOSI = 11;
|
||||
static const uint8_t MISO = 13;
|
||||
static const uint8_t SCK = 12;
|
||||
|
||||
// SD Card CS
|
||||
#define SDCARD_CS 10
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
||||
@@ -0,0 +1,23 @@
|
||||
; LilyGo T-Beam-BPF (144-148Mhz) ~5 Watt (37 dBm)
|
||||
[env:t-beam-bpf]
|
||||
custom_meshtastic_hw_model = 124
|
||||
custom_meshtastic_hw_model_slug = TBEAM_BPF
|
||||
custom_meshtastic_architecture = esp32s3
|
||||
custom_meshtastic_actively_supported = true
|
||||
custom_meshtastic_support_level = 3
|
||||
custom_meshtastic_display_name = LILYGO T-Beam BPF
|
||||
custom_meshtastic_images = tbeam-1w.svg
|
||||
custom_meshtastic_tags = LilyGo
|
||||
|
||||
extends = esp32s3_base
|
||||
board = t-beam-bpf
|
||||
board_build.partitions = default_16MB.csv
|
||||
board_check = true
|
||||
|
||||
lib_deps =
|
||||
${esp32s3_base.lib_deps}
|
||||
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-I variants/esp32s3/t-beam-bpf
|
||||
-D T_BEAM_BPF
|
||||
@@ -0,0 +1,70 @@
|
||||
// LilyGo T-Beam-BPF variant.h
|
||||
// Configuration based on LilyGO utilities.h and RF documentation
|
||||
|
||||
// Hardware is restricted to the amateur 2m band (144-148 MHz).
|
||||
#define HAS_HAM_2M_ONLY 1
|
||||
|
||||
// I2C for OLED display (SH1106 at 0x3C)
|
||||
#define I2C_SDA 8
|
||||
#define I2C_SCL 9
|
||||
|
||||
// GPS - Quectel L76K. Per schematic sheet 7:
|
||||
|
||||
#define GPS_RX_PIN 5
|
||||
#define GPS_TX_PIN 6
|
||||
#define GPS_1PPS_PIN 7
|
||||
#define HAS_GPS 1
|
||||
#define GPS_BAUDRATE 9600
|
||||
|
||||
// Buttons
|
||||
#define BUTTON_PIN 0 // BUTTON 1
|
||||
#define ALT_BUTTON_PIN 3 // BUTTON 2
|
||||
|
||||
// SPI (shared by LoRa and SD)
|
||||
#define SPI_MOSI 11
|
||||
#define SPI_SCK 12
|
||||
#define SPI_MISO 13
|
||||
#define SPI_CS 10
|
||||
|
||||
// SD Card
|
||||
#define HAS_SDCARD
|
||||
#define SDCARD_USE_SPI1
|
||||
// #define SDCARD_CS SPI_CS (already defined in pins_arduino.h)
|
||||
|
||||
// LoRa Radio - SX1278 144-148Mhz
|
||||
#define USE_RF95
|
||||
#define LORA_SCK SPI_SCK
|
||||
#define LORA_MISO SPI_MISO
|
||||
#define LORA_MOSI SPI_MOSI
|
||||
#define LORA_CS 1
|
||||
#define LORA_RESET 18
|
||||
#define LORA_IRQ 14
|
||||
#define LORA_DIO0 LORA_IRQ
|
||||
#define LORA_DIO1 21
|
||||
#define RF95_RXEN 39 // LNA enable - HIGH during RX
|
||||
|
||||
// CRITICAL: Radio power enable - MUST be HIGH before lora.begin()!
|
||||
// GPIO 16 powers the SX1278 via LDO
|
||||
#define RF95_POWER_EN 16
|
||||
|
||||
// +27dBm PA
|
||||
// LilyGo Docs specify SX1278 power must be capped at 10
|
||||
#define RF95_MAX_POWER 10
|
||||
// PA curve mapping (TX values 1-10)
|
||||
// Measurements taken with 5V USB power (max 37 dBm on battery power)
|
||||
// Input values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
|
||||
// Output values: 0, 34, 35, 36, 36, 37, 37, 38, 38, 38
|
||||
#define NUM_PA_POINTS 10
|
||||
#define TX_GAIN_LORA 0, 32, 32, 32, 31, 31, 30, 30, 29, 28
|
||||
|
||||
// Display - SH1106 OLED (128x64)
|
||||
#define USE_SH1106
|
||||
#define OLED_WIDTH 128
|
||||
#define OLED_HEIGHT 64
|
||||
|
||||
// 32768 Hz crystal present
|
||||
#define HAS_32768HZ 1
|
||||
|
||||
// PMU
|
||||
#define HAS_AXP2101
|
||||
// #define PMU_IRQ 4 // Leave disabled for now
|
||||
@@ -55,9 +55,9 @@ build_flags =
|
||||
-D HAS_TFT=1
|
||||
-D USE_I2S_BUZZER
|
||||
-D RAM_SIZE=5120
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_CONF_INCLUDE_SIMPLE
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_CONF_INCLUDE_SIMPLE
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||
-D LV_USE_SYSMON=0
|
||||
-D LV_USE_PROFILER=0
|
||||
-D LV_USE_PERF_MONITOR=0
|
||||
@@ -72,7 +72,6 @@ build_flags =
|
||||
; -D CALIBRATE_TOUCH=0
|
||||
-D LGFX_SCREEN_WIDTH=240
|
||||
-D LGFX_SCREEN_HEIGHT=320
|
||||
-D LGFX_BUFSIZE=153600
|
||||
-D DISPLAY_SIZE=320x240 ; landscape mode
|
||||
-D LGFX_DRIVER=LGFX_TDECK
|
||||
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_T_DECK.h\"
|
||||
@@ -80,11 +79,13 @@ build_flags =
|
||||
; -D GFX_DRIVER_INC=\"graphics/LVGL/LVGL_T_DECK.h\"
|
||||
; -D LV_USE_ST7789=1
|
||||
-D VIEW_320x240
|
||||
; -D USE_DOUBLE_BUFFER
|
||||
-D USE_PACKET_API
|
||||
-D MAP_FULL_REDRAW
|
||||
; -D CUSTOM_TOUCH_DRIVER
|
||||
-D CUSTOM_TOUCH_DRIVER
|
||||
|
||||
lib_deps =
|
||||
${env:t-deck.lib_deps}
|
||||
${device-ui_base.lib_deps}
|
||||
;https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip
|
||||
# renovate: datasource=github-tags depName=bb_captouch packageName=bitbank2/bb_captouch
|
||||
https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
[env:t-impulse-plus]
|
||||
custom_meshtastic_hw_model = 135
|
||||
custom_meshtastic_hw_model_slug = T_IMPULSE_PLUS
|
||||
custom_meshtastic_architecture = nrf52840
|
||||
custom_meshtastic_actively_supported = true
|
||||
custom_meshtastic_support_level = 1
|
||||
custom_meshtastic_display_name = LILYGO T-Impulse Plus
|
||||
custom_meshtastic_tags = LilyGo
|
||||
custom_meshtastic_requires_dfu = true
|
||||
|
||||
extends = nrf52840_base
|
||||
board = t-impulse-plus
|
||||
board_level = pr
|
||||
|
||||
build_flags = ${nrf52840_base.build_flags}
|
||||
-I variants/nrf52840/t-impulse-plus
|
||||
-D T_IMPULSE_PLUS
|
||||
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/t-impulse-plus>
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* variant.cpp - Digital pin mapping for LilyGo T-Impulse Plus
|
||||
*
|
||||
* Board: T-Impulse Plus V1.0 (nRF52840)
|
||||
* Hardware:
|
||||
* - SSD1315 OLED
|
||||
* - SX1262 (S62F)
|
||||
* - MIA-M10Q GPS
|
||||
* - ICM20948 IMU
|
||||
* - ZD25WQ32C Flash
|
||||
* - TTP223 Touch Button
|
||||
* - Vibration Motor
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "nrf.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
extern "C" {
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
// D0-D6: LoRa SX1262 (S62F module) SPI + control
|
||||
2, // D0 P0.02 SX1262_RST
|
||||
29, // D1 P0.29 SX1262_DIO1
|
||||
31, // D2 P0.31 SX1262_BUSY
|
||||
46, // D3 P1.14 SX1262_CS
|
||||
3, // D4 P0.03 SPI_SCK
|
||||
30, // D5 P0.30 SPI_MISO
|
||||
28, // D6 P0.28 SPI_MOSI
|
||||
|
||||
// D7-D8: RF switch control
|
||||
45, // D7 P1.13 SX1262_RF_VC1 (TXEN)
|
||||
39, // D8 P1.07 SX1262_RF_VC2 (RXEN)
|
||||
|
||||
// D9-D11: GPS (u-blox MIA-M10Q)
|
||||
44, // D9 P1.12 GPS_TX (MCU TX -> GPS RX)
|
||||
43, // D10 P1.11 GPS_RX (MCU RX <- GPS TX)
|
||||
42, // D11 P1.10 GPS_EN
|
||||
|
||||
// D12-D13: Display I2C (SSD1315)
|
||||
20, // D12 P0.20 SCREEN_SDA
|
||||
15, // D13 P0.15 SCREEN_SCL
|
||||
|
||||
// D14-D15: Sensor I2C (ICM20948, SGM41562)
|
||||
40, // D14 P1.08 IMU_SDA
|
||||
11, // D15 P0.11 IMU_SCL
|
||||
|
||||
// D16-D17: Battery management
|
||||
5, // D16 P0.05 BATTERY_ADC
|
||||
25, // D17 P0.25 BATTERY_MEASUREMENT_CONTROL
|
||||
|
||||
// D18: Touch button (TTP223)
|
||||
36, // D18 P1.04 TTP223_KEY
|
||||
|
||||
// D19: Vibration motor
|
||||
22, // D19 P0.22 VIBRATION_MOTOR
|
||||
|
||||
// D20: LDO enable
|
||||
14, // D20 P0.14 RT9080_EN
|
||||
|
||||
// D21-D26: Flash QSPI (ZD25WQ32C)
|
||||
12, // D21 P0.12 FLASH_CS
|
||||
4, // D22 P0.04 FLASH_SCLK
|
||||
6, // D23 P0.06 FLASH_IO0
|
||||
41, // D24 P1.09 FLASH_IO1
|
||||
8, // D25 P0.08 FLASH_IO2
|
||||
26, // D26 P0.26 FLASH_IO3
|
||||
|
||||
// D27-D28: Interrupt lines
|
||||
7, // D27 P0.07 ICM20948_INT
|
||||
16, // D28 P0.16 SGM41562_INT
|
||||
|
||||
// D29: Boot button
|
||||
24, // D29 P0.24 BOOT
|
||||
};
|
||||
}
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
// Flash CS high (deselect)
|
||||
pinMode(PIN_QSPI_CS, OUTPUT);
|
||||
digitalWrite(PIN_QSPI_CS, HIGH);
|
||||
|
||||
// Enable battery voltage measurement
|
||||
pinMode(BAT_READ, OUTPUT);
|
||||
digitalWrite(BAT_READ, HIGH);
|
||||
|
||||
// Enable RT9080 LDO
|
||||
pinMode(D20, OUTPUT);
|
||||
digitalWrite(D20, HIGH);
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
#ifndef _T_IMPULSE_PLUS_H_
|
||||
#define _T_IMPULSE_PLUS_H_
|
||||
#include "WVariant.h"
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Clock Configuration
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
#define USE_LFXO
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Pin Capacity Definitions
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define PINS_COUNT (30u)
|
||||
#define NUM_DIGITAL_PINS (30u)
|
||||
#define NUM_ANALOG_INPUTS (1u)
|
||||
#define NUM_ANALOG_OUTPUTS (0u)
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Digital Pin Mapping
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define D0 0 // P0.02 SX1262_RST
|
||||
#define D1 1 // P0.29 SX1262_DIO1
|
||||
#define D2 2 // P0.31 SX1262_BUSY
|
||||
#define D3 3 // P1.14 SX1262_CS
|
||||
#define D4 4 // P0.03 SPI_SCK
|
||||
#define D5 5 // P0.30 SPI_MISO
|
||||
#define D6 6 // P0.28 SPI_MOSI
|
||||
#define D7 7 // P1.13 RF_VC1 (TXEN)
|
||||
#define D8 8 // P1.07 RF_VC2 (RXEN)
|
||||
#define D9 9 // P1.12 GPS module TX → MCU RX
|
||||
#define D10 10 // P1.11 GPS module RX ← MCU TX
|
||||
#define D11 11 // P1.10 GPS_EN (active LOW)
|
||||
#define D12 12 // P0.20 SCREEN_SDA
|
||||
#define D13 13 // P0.15 SCREEN_SCL
|
||||
#define D14 14 // P1.08 IMU_SDA
|
||||
#define D15 15 // P0.11 IMU_SCL
|
||||
#define D16 16 // P0.05 BATTERY_ADC
|
||||
#define D17 17 // P0.25 BATTERY_CTL
|
||||
#define D18 18 // P1.04 TTP223_KEY
|
||||
#define D19 19 // P0.22 VIBRATION_MOTOR
|
||||
#define D20 20 // P0.14 RT9080_EN
|
||||
#define D21 21 // P0.12 FLASH_CS
|
||||
#define D22 22 // P0.04 FLASH_SCLK
|
||||
#define D23 23 // P0.06 FLASH_IO0
|
||||
#define D24 24 // P1.09 FLASH_IO1
|
||||
#define D25 25 // P0.08 FLASH_IO2
|
||||
#define D26 26 // P0.26 FLASH_IO3
|
||||
#define D27 27 // P0.07 ICM20948_INT
|
||||
#define D28 28 // P0.16 SGM41562_INT
|
||||
#define D29 29 // P0.24 BOOT
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// LED Configuration (no physical LED)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Button Configuration (TTP223 capacitive touch)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define PIN_BUTTON_TOUCH D18
|
||||
#define BUTTON_TOUCH_ACTIVE_LOW true
|
||||
#define BUTTON_TOUCH_ACTIVE_PULLUP false
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Analog Pin Definitions
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define PIN_VBAT D16 // P0.05 Battery voltage sense
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// I2C Configuration
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Primary I2C: Display (SSD1315)
|
||||
#define PIN_WIRE_SDA D12 // P0.20
|
||||
#define PIN_WIRE_SCL D13 // P0.15
|
||||
|
||||
// Secondary I2C: IMU (ICM20948) + PMU (SGM41562)
|
||||
#define WIRE_INTERFACES_COUNT 2
|
||||
#define PIN_WIRE1_SDA D14 // P1.08
|
||||
#define PIN_WIRE1_SCL D15 // P0.11
|
||||
#define I2C_NO_RESCAN
|
||||
|
||||
static const uint8_t SDA = PIN_WIRE_SDA;
|
||||
static const uint8_t SCL = PIN_WIRE_SCL;
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Display (SSD1315, compatible with SSD1306 driver)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define HAS_SCREEN 1
|
||||
#define USE_SSD1306 1
|
||||
#define OLED_TINY
|
||||
#define OLED_GEOMETRY_OVERRIDE GEOMETRY_64_32
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// SPI Configuration (SX1262 LoRa)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define SPI_INTERFACES_COUNT 1
|
||||
#define PIN_SPI_SCK D4 // P0.03
|
||||
#define PIN_SPI_MISO D5 // P0.30
|
||||
#define PIN_SPI_MOSI D6 // P0.28
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// SX1262 LoRa (S62F module)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define USE_SX1262
|
||||
#define SX126X_CS D3
|
||||
#define SX126X_DIO1 D1
|
||||
#define SX126X_BUSY D2
|
||||
#define SX126X_RESET D0
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_TXEN D7 // RF_VC1
|
||||
#define SX126X_RXEN D8 // RF_VC2
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Power Management
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define BAT_READ D17 // P0.25 Battery measurement control (HIGH = enable)
|
||||
#define BATTERY_PIN PIN_VBAT
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#define ADC_MULTIPLIER 2.0
|
||||
#define AREF_VOLTAGE 3.6
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// GPS (u-blox MIA-M10Q)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define GPS_UBLOX
|
||||
#define HAS_GPS 1
|
||||
#define GPS_RX_PIN D9 // P1.12 — MCU RX, wired to GPS module TX
|
||||
#define GPS_TX_PIN D10 // P1.11 — MCU TX, wired to GPS module RX
|
||||
#define PIN_GPS_EN D11 // P1.10
|
||||
#define GPS_EN_ACTIVE LOW
|
||||
#define GPS_BAUDRATE 38400
|
||||
#define GPS_THREAD_INTERVAL 50
|
||||
#define PIN_SERIAL1_TX GPS_TX_PIN
|
||||
#define PIN_SERIAL1_RX GPS_RX_PIN
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// On-board QSPI Flash (ZD25WQ32CEIGR)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define PIN_QSPI_SCK D22 // P0.04
|
||||
#define PIN_QSPI_CS D21 // P0.12
|
||||
#define PIN_QSPI_IO0 D23 // P0.06
|
||||
#define PIN_QSPI_IO1 D24 // P1.09
|
||||
#define PIN_QSPI_IO2 D25 // P0.08
|
||||
#define PIN_QSPI_IO3 D26 // P0.26
|
||||
|
||||
#define EXTERNAL_FLASH_DEVICES W25Q32JV_IQ
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Vibration Motor (GPIO active-high)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define LED_NOTIFICATION D19 // P0.22
|
||||
#define HAPTIC_FEEDBACK_PIN LED_NOTIFICATION
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// IMU (ICM20948 on Wire1)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define HAS_ICM20948
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Charger (SGM41562 on Wire1 @ 0x03)
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define HAS_SGM41562
|
||||
#define SGM41562_WIRE Wire1
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// Compatibility Definitions
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PIN_SERIAL2_RX (-1)
|
||||
#define PIN_SERIAL2_TX (-1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _T_IMPULSE_PLUS_H_
|
||||
Reference in New Issue
Block a user