Merge branch 'master' into Routing

pull/6344/head
Thomas Göttgens 2025-03-29 13:08:41 +01:00 zatwierdzone przez GitHub
commit 61b64fb0e2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
113 zmienionych plików z 5664 dodań i 383 usunięć

Wyświetl plik

@ -72,6 +72,15 @@ body:
validations:
required: true
- type: checkboxes
id: mui
attributes:
label: Is this bug report about any UI component firmware like InkHUD or Meshtatic UI (MUI)?
options:
- label: Meshtastic UI aka MUI colorTFT
- label: InkHUD ePaper
- label: OLED slide UI on any display
- type: input
id: version
attributes:

Wyświetl plik

@ -1,7 +1,6 @@
## 🙏 Thank you for sending in a pull request, here's some tips to get started!
### ❌ (Please delete all these tips and replace them with your text) ❌
## Thank you for sending in a pull request, here's some tips to get started!
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
@ -12,4 +11,17 @@
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
- If your other co-developers have comments on your PR please tweak as needed.
- Please also enable "Allow edits by maintainers".
- Please do not submit untested code.
- If you do not have the affected hardware to test your code changes adequately against regressions, please indicate this, so that contributors and commnunity members can help test your changes.
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord
## 🤝 Attestations
- [ ] I have tested that my proposed changes behave as described.
- [ ] I have tested that my proposed changes do not cause any obvious regressions on the following devices:
- [ ] Heltec (Lora32) V3
- [ ] LilyGo T-Deck
- [ ] LilyGo T-Beam
- [ ] RAK WisBlock 4631
- [ ] Seeed Studio T-1000E tracker card
- [ ] Other (please specify below)

Wyświetl plik

@ -9,14 +9,14 @@ plugins:
lint:
enabled:
- prettier@3.5.3
- trufflehog@3.88.17
- yamllint@1.36.2
- trufflehog@3.88.18
- yamllint@1.37.0
- bandit@1.8.3
- checkov@3.2.386
- checkov@3.2.394
- terrascan@1.19.9
- trivy@0.60.0
- taplo@0.9.3
- ruff@0.11.0
- ruff@0.11.2
- isort@6.0.1
- markdownlint@0.44.0
- oxipng@9.1.4
@ -28,7 +28,7 @@ lint:
- shellcheck@0.10.0
- black@25.1.0
- git-diff-check
- gitleaks@8.24.0
- gitleaks@8.24.2
- clang-format@16.0.3
ignore:
- linters: [ALL]

Wyświetl plik

@ -45,11 +45,11 @@ lib_deps =
${networking_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
https://github.com/meshtastic/esp32_https_server/archive/23665b3adc080a311dcbb586ed5941b5f94d6ea2.zip
h2zero/NimBLE-Arduino@^1.4.3
https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
lewisxhe/XPowersLib@^0.2.7
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
rweather/Crypto@^0.4.0
lib_ignore =

Wyświetl plik

@ -1,6 +1,6 @@
[esp32c6_base]
extends = esp32_base
platform = https://github.com/Jason2866/platform-espressif32.git#22faa566df8c789000f8136cd8d0aca49617af55
platform = https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
build_flags =
${arduino_base.build_flags}
-Wall
@ -25,7 +25,7 @@ lib_deps =
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
lewisxhe/XPowersLib@^0.2.7
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
rweather/Crypto@^0.4.0
build_src_filter =

Wyświetl plik

@ -4,7 +4,7 @@ platform = platformio/nordicnrf52@^10.7.0
extends = arduino_base
platform_packages =
; our custom Git version until they merge our PR
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino.git#e13f5820002a4fb2a5e6754b42ace185277e5adf
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf
platformio/toolchain-gccarmnoneeabi@~1.90301.0
build_type = debug

Wyświetl plik

@ -6,7 +6,7 @@ build_flags = ${nrf52_base.build_flags}
lib_deps =
${nrf52_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/e31a8825ea3300b163a0a3c1ddd5de34e10e1371.zip
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.

Wyświetl plik

@ -1,6 +1,6 @@
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
[portduino_base]
platform = https://github.com/meshtastic/platform-native.git#df71ed0040e9aad767a002829330965b78fc452a
platform = https://github.com/meshtastic/platform-native/archive/c5bd469ab9b5a6966321e09557b27d906961da63.zip
framework = arduino
build_src_filter =
@ -26,7 +26,7 @@ lib_deps =
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
lovyan03/LovyanGFX@^1.2.0
https://github.com/pine64/libch341-spi-userspace#a9b17e3452f7fb747000d9b4ad4409155b39f6ef
https://github.com/pine64/libch341-spi-userspace/archive/a9b17e3452f7fb747000d9b4ad4409155b39f6ef.zip
build_flags =
${arduino_base.build_flags}

Wyświetl plik

@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.4.3
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m

Wyświetl plik

@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.4.3
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m

Wyświetl plik

@ -1,13 +1,14 @@
[stm32_base]
extends = arduino_base
platform = platformio/ststm32
platform_packages = platformio/framework-arduinoststm32@^4.20900.0
platform = ststm32
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
extra_scripts =
${env.extra_scripts}
post:extra_scripts/extra_stm32.py
build_type = release
;board_build.flash_offset = 0x08000000
build_flags =
build_flags =
${arduino_base.build_flags}
-flto
-Isrc/platform/stm32wl -g
@ -18,27 +19,24 @@ build_flags =
-DMESHTASTIC_EXCLUDE_SCREEN
-DMESHTASTIC_EXCLUDE_MQTT
-DMESHTASTIC_EXCLUDE_BLUETOOTH
-DMESHTASTIC_EXCLUDE_PKI
-DMESHTASTIC_EXCLUDE_GPS
; -DVECT_TAB_OFFSET=0x08000000
-DconfigUSE_CMSIS_RTOS_V2=1
; -DSPI_MODE_0=SPI_MODE0
;-DDEBUG_MUTE
-fmerge-all-constants
-ffunction-sections
-fdata-sections
build_src_filter =
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
board_upload.offset_address = 0x08000000
upload_protocol = stlink
debug_tool = stlink
lib_deps =
${env.lib_deps}
charlesbaynham/OSFS@^1.2.3
jgromes/RadioLib@7.0.2
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
${radiolib_base.lib_deps}
https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip
lib_ignore =
mathertel/OneButton@2.6.1
Wire
Wire

Wyświetl plik

@ -1,5 +1,6 @@
# Module: RF95 # Adafruit RFM9x
# Reset: 25
# CS: 7
# IRQ: 22
# Busy: 23
Lora:
Module: RF95 # Adafruit RFM9x
Reset: 25
CS: 7
IRQ: 22
# Busy: 23

Wyświetl plik

@ -17,8 +17,8 @@ SET "LOGCOUNTER=0"
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
SET "C3=esp32c3"
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3"
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core t-watch-s3 tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite"
GOTO getopts
:help

Wyświetl plik

@ -22,6 +22,7 @@ BIGDB_8MB=(
"icarus"
"seeed-xiao-s3"
"tbeam-s3-core"
"t-watch-s3"
"tracksenger"
)
BIGDB_16MB=(
@ -33,7 +34,6 @@ BIGDB_16MB=(
"m5stack-cores3"
"station-g2"
"t-eth-elite"
"t-watch-s3"
)
S3_VARIANTS=(
"s3"

Wyświetl plik

@ -0,0 +1,53 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "elecrow_eink",
"mcu": "nrf52840",
"variant": "ELECROW-ThinkNode-M1",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"onboard_tools": ["jlink"],
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "elecrow eink",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "FIXME",
"vendor": "ELECROW"
}

Wyświetl plik

@ -0,0 +1,22 @@
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports
Import("env")
# Custom HEX from ELF
env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf",
env.VerboseAction(
" ".join(
[
"$OBJCOPY",
"-O",
"ihex",
"-R",
".eeprom",
"$BUILD_DIR/${PROGNAME}.elf",
"$BUILD_DIR/${PROGNAME}.hex",
]
),
"Building $BUILD_DIR/${PROGNAME}.hex",
),
)

Wyświetl plik

@ -56,11 +56,11 @@ build_flags = -Wno-missing-field-initializers
monitor_speed = 115200
monitor_filters = direct
lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/e16cee124fe26490cb14880c679321ad8ac89c95.zip
mathertel/OneButton@2.6.1
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
https://github.com/meshtastic/ArduinoThread.git#7c3ee9e1951551b949763b1f5280f8db1fa4068d
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
https://github.com/meshtastic/TinyGPSPlus/archive/71a82db35f3b973440044c476d4bcdc673b104f4.zip
https://github.com/meshtastic/ArduinoThread/archive/7c3ee9e1951551b949763b1f5280f8db1fa4068d.zip
nanopb/Nanopb@0.4.91
erriez/ErriezCRC32@1.0.1
@ -94,7 +94,7 @@ lib_deps =
[device-ui_base]
lib_deps =
https://github.com/meshtastic/device-ui.git#74e739ed4532ca10393df9fc89ae5a22f0bab2b1
https://github.com/meshtastic/device-ui/archive/b1e862e8b2a604a8d911e9d7a27f6e80f1176c21.zip
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)
@ -127,13 +127,13 @@ lib_deps =
ClosedCube OPT3001@1.1.2
emotibit/EmotiBit MLX90632@1.0.8
adafruit/Adafruit MLX90614 Library@2.1.5
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip
boschsensortec/BME68x Sensor Library@1.1.40407
https://github.com/KodinLanewave/INA3221@1.0.1
https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip
mprograms/QMC5883LCompass@1.2.3
dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
https://github.com/DFRobot/DFRobot_RainfallSensor#38fea5e02b40a5430be6dab39a99a6f6347d667e
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
robtillaart/INA226@0.6.0
; Health Sensor Libraries

@ -1 +1 @@
Subproject commit 14ec205865592fcfa798065bb001a549fc77b438
Subproject commit f00e96f12da48abfa9a992f8b5546fd75a370250

Wyświetl plik

@ -41,10 +41,8 @@ class AudioThread : public concurrency::OSThread
delete i2sRtttl;
i2sRtttl = nullptr;
}
if (rtttlFile != nullptr) {
delete rtttlFile;
rtttlFile = nullptr;
}
delete rtttlFile;
rtttlFile = nullptr;
setCPUFast(false);
}

Wyświetl plik

@ -47,7 +47,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
#ifdef USERPREFS_BUTTON_PIN
int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
#endif
#if defined(HELTEC_CAPSULE_SENSOR_V3)
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
this->userButton = OneButton(pin, false, false);
#elif defined(BUTTON_ACTIVE_LOW)
this->userButton = OneButton(pin, BUTTON_ACTIVE_LOW, BUTTON_ACTIVE_PULLUP);
@ -73,23 +73,28 @@ ButtonThread::ButtonThread() : OSThread("Button")
userButton.setDebounceMs(1);
userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton
#ifndef T_DECK // T-Deck immediately wakes up after shutdown, so disable this function
#if !defined(T_DECK) && \
!defined( \
ELECROW_ThinkNode_M2) // T-Deck immediately wakes up after shutdown, Thinknode M2 has this on the smaller ALT button
userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop);
#endif
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
#if defined(ELECROW_ThinkNode_M2)
this->userButtonAlt = OneButton(BUTTON_PIN_ALT, false, false);
#else
this->userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
#endif
#ifdef INPUT_PULLUP_SENSE
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
#endif
userButtonAlt.attachClick(userButtonPressed);
userButtonAlt.attachClick(userButtonPressedScreen);
userButtonAlt.setClickMs(BUTTON_CLICK_MS);
userButtonAlt.setPressMs(BUTTON_LONGPRESS_MS);
userButtonAlt.setDebounceMs(1);
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
#endif
@ -117,6 +122,40 @@ int32_t ButtonThread::runOnce()
canSleep = true; // Assume we should not keep the board awake
#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
// #if defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2)
// buzzer_updata();
// if (buttonPressed) {
// buttonPressed = false; // 清除标志
// LOG_INFO("PIN_BUTTON2 pressed!"); // 串口打印信息
// // off_currentTime = millis();
// while (digitalRead(PIN_BUTTON2) == HIGH) {
// if (cont < 40) {
// // unsigned long currentTime = millis(); // 获取当前时间
// // if (currentTime - off_currentTime >= 1000) {
// cont++;
// // off_currentTime = currentTime;
// // }
// delay(100);
// } else {
// currentState = OFF;
// isBuzzing = false;
// cont = 0;
// BEEP_STATE = false;
// analogWrite(M2_buzzer, 0);
// pinMode(M2_buzzer, INPUT);
// screen->setOn(false);
// cont = 0;
// LOG_INFO("GGGGGGGGGGGGGGGGGGGGGGGGG");
// pinMode(1, OUTPUT);
// digitalWrite(1, LOW);
// pinMode(6, OUTPUT);
// digitalWrite(6, LOW);
// }
// }
// }
// #endif
userButton.tick();
canSleep &= userButton.isIdle();
#elif defined(ARCH_PORTDUINO)
@ -166,6 +205,14 @@ int32_t ButtonThread::runOnce()
break;
}
case BUTTON_EVENT_PRESSED_SCREEN: {
// turn screen on or off
screen_flag = !screen_flag;
if (screen)
screen->setOn(screen_flag);
break;
}
case BUTTON_EVENT_DOUBLE_PRESSED: {
LOG_BUTTON("Double press!");
service->refreshLocalMeshNode();
@ -192,7 +239,16 @@ int32_t ButtonThread::runOnce()
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
}
break;
#elif defined(ELECROW_ThinkNode_M2)
case 3:
LOG_INFO("3 clicks: toggle buzzer");
buzzer_flag = !buzzer_flag;
if (buzzer_flag) {
playBeep();
}
break;
#endif
#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo
// 4 clicks: toggle backlight
case 4:

Wyświetl plik

@ -24,6 +24,7 @@ class ButtonThread : public concurrency::OSThread
enum ButtonEventType {
BUTTON_EVENT_NONE,
BUTTON_EVENT_PRESSED,
BUTTON_EVENT_PRESSED_SCREEN,
BUTTON_EVENT_DOUBLE_PRESSED,
BUTTON_EVENT_MULTI_PRESSED,
BUTTON_EVENT_LONG_PRESSED,
@ -42,7 +43,6 @@ class ButtonThread : public concurrency::OSThread
int beforeLightSleep(void *unused);
int afterLightSleep(esp_sleep_wakeup_cause_t cause);
#endif
private:
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
static OneButton userButton; // Static - accessed from an interrupt
@ -64,6 +64,8 @@ class ButtonThread : public concurrency::OSThread
// set during IRQ
static volatile ButtonEventType btnEvent;
bool buzzer_flag = false;
bool screen_flag = true;
// Store click count during callback, for later use
volatile int multipressClickCount = 0;
@ -72,6 +74,12 @@ class ButtonThread : public concurrency::OSThread
// IRQ callbacks
static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; }
static void userButtonPressedScreen()
{
if (millis() > c_holdOffTime) {
btnEvent = BUTTON_EVENT_PRESSED_SCREEN;
}
}
static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; }
static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid
static void userButtonPressedLongStart();

Wyświetl plik

@ -29,30 +29,6 @@ SPIClass SPI1(HSPI);
#endif // HAS_SDCARD
#if defined(ARCH_STM32WL)
uint16_t OSFS::startOfEEPROM = 1;
uint16_t OSFS::endOfEEPROM = 2048;
// 3) How do I read from the medium?
void OSFS::readNBytes(uint16_t address, unsigned int num, byte *output)
{
for (uint16_t i = address; i < address + num; i++) {
*output = EEPROM.read(i);
output++;
}
}
// 4) How to I write to the medium?
void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
{
for (uint16_t i = address; i < address + num; i++) {
EEPROM.update(i, *input);
input++;
}
}
#endif
/**
* @brief Copies a file from one location to another.
*
@ -62,33 +38,7 @@ void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
*/
bool copyFile(const char *from, const char *to)
{
#ifdef ARCH_STM32WL
unsigned char cbuffer[2048];
// Var to hold the result of actions
OSFS::result r;
r = OSFS::getFile(from, cbuffer);
if (r == notfound) {
LOG_ERROR("Failed to open source file %s", from);
return false;
} else if (r == noerr) {
r = OSFS::newFile(to, cbuffer, true);
if (r == noerr) {
return true;
} else {
LOG_ERROR("OSFS Error %d", r);
return false;
}
} else {
LOG_ERROR("OSFS Error %d", r);
return false;
}
return true;
#elif defined(FSCom)
#ifdef FSCom
// take SPI Lock
concurrency::LockGuard g(spiLock);
unsigned char cbuffer[16];
@ -127,13 +77,7 @@ bool copyFile(const char *from, const char *to)
*/
bool renameFile(const char *pathFrom, const char *pathTo)
{
#ifdef ARCH_STM32WL
if (copyFile(pathFrom, pathTo) && (OSFS::deleteFile(pathFrom) == OSFS::result::NO_ERROR)) {
return true;
} else {
return false;
}
#elif defined(FSCom)
#ifdef FSCom
#ifdef ARCH_ESP32
// take SPI Lock

Wyświetl plik

@ -15,13 +15,11 @@
#endif
#if defined(ARCH_STM32WL)
// STM32WL series 2 Kbytes (8 rows of 256 bytes)
#include <EEPROM.h>
#include <OSFS.h>
// Useful consts
const OSFS::result noerr = OSFS::result::NO_ERROR;
const OSFS::result notfound = OSFS::result::FILE_NOT_FOUND;
// STM32WL
#include "LittleFS.h"
#define FSCom InternalFS
#define FSBegin() FSCom.begin()
using namespace STM32_LittleFS_Namespace;
#endif
#if defined(ARCH_RP2040)

Wyświetl plik

@ -391,7 +391,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual bool isVbusIn() override
{
#ifdef EXT_PWR_DETECT
#ifdef HELTEC_CAPSULE_SENSOR_V3
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
// if external powered that pin will be pulled down
if (digitalRead(EXT_PWR_DETECT) == LOW) {
return true;
@ -541,7 +541,7 @@ Power::Power() : OSThread("Power")
bool Power::analogInit()
{
#ifdef EXT_PWR_DETECT
#ifdef HELTEC_CAPSULE_SENSOR_V3
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
pinMode(EXT_PWR_DETECT, INPUT_PULLUP);
#else
pinMode(EXT_PWR_DETECT, INPUT);
@ -713,6 +713,9 @@ void Power::readPowerStatus()
const PowerStatus powerStatus2 = PowerStatus(hasBattery, usbPowered, isCharging, batteryVoltageMv, batteryChargePercent);
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d", powerStatus2.getHasUSB(), powerStatus2.getIsCharging(),
powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG)
power_num = powerStatus2.getBatteryVoltageMv();
#endif
newStatus.notifyObservers(&powerStatus2);
#ifdef DEBUG_HEAP
if (lastheap != memGet.getFreeHeap()) {
@ -756,9 +759,13 @@ void Power::readPowerStatus()
// If we have a battery at all and it is less than 0%, force deep sleep if we have more than 10 low readings in
// a row. NOTE: min LiIon/LiPo voltage is 2.0 to 2.5V, current OCV min is set to 3100 that is large enough.
//
if (batteryLevel && powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
if (batteryLevel->getBattVoltage() < OCV[NUM_OCV_POINTS - 1]) {
low_voltage_counter++;
#if defined(ELECROW_ThinkNode_M1)
low_voltage_counter_led3 = low_voltage_counter;
#endif
LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter);
if (low_voltage_counter > 10) {
#ifdef ARCH_NRF52
@ -771,7 +778,13 @@ void Power::readPowerStatus()
}
} else {
low_voltage_counter = 0;
#if defined(ELECROW_ThinkNode_M1)
low_voltage_counter_led3 = low_voltage_counter;
#endif
}
#ifdef POWER_CFG
low_voltage_counter_led3 = low_voltage_counter;
#endif
}
}

Wyświetl plik

@ -30,8 +30,11 @@ struct ToneDuration {
#define NOTE_B3 247
#define NOTE_CS4 277
const int DURATION_1_8 = 125; // 1/8 note
const int DURATION_1_4 = 250; // 1/4 note
const int DURATION_1_8 = 125; // 1/8 note
const int DURATION_1_4 = 250; // 1/4 note
const int DURATION_1_2 = 500; // 1/2 note
const int DURATION_3_4 = 750; // 1/4 note
const int DURATION_1_1 = 1000; // 1/1 note
void playTones(const ToneDuration *tone_durations, int size)
{
@ -55,6 +58,12 @@ void playBeep()
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}
void playLongBeep()
{
ToneDuration melody[] = {{NOTE_B3, DURATION_1_1}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}
void playGPSEnableBeep()
{
ToneDuration melody[] = {{NOTE_C3, DURATION_1_8}, {NOTE_FS3, DURATION_1_4}, {NOTE_CS4, DURATION_1_4}};

Wyświetl plik

@ -1,6 +1,7 @@
#pragma once
void playBeep();
void playLongBeep();
void playStartMelody();
void playShutdownMelody();
void playGPSEnableBeep();

Wyświetl plik

@ -1200,12 +1200,12 @@ GnssModel_t GPS::probe(int serialSpeed)
PROBE_SIMPLE("LC86", "$PQTMVERNO*58", "$PQTMVERNO,LC86", GNSS_MODEL_AG3352, 500);
PROBE_SIMPLE("L76K", "$PCAS06,0*1B", "$GPTXT,01,01,02,SW=", GNSS_MODEL_MTK, 500);
// Close all NMEA sentences, valid for L76B MTK platform (Waveshare Pico GPS)
// Close all NMEA sentences, valid for MTK3333 and MTK3339 platforms
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
delay(20);
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
{"LS20031", "MC-1513", GNSS_MODEL_LS20031}};
{"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}};
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};

Wyświetl plik

@ -128,16 +128,24 @@ bool EInkDisplay::connect()
#ifdef PIN_EINK_EN
// backlight power, HIGH is backlight on, LOW is off
pinMode(PIN_EINK_EN, OUTPUT);
#ifdef ELECROW_ThinkNode_M1
digitalWrite(PIN_EINK_EN, LOW);
#else
digitalWrite(PIN_EINK_EN, HIGH);
#endif
#endif
#if defined(TTGO_T_ECHO)
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1)
{
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init();
#ifdef ELECROW_ThinkNode_M1
adafruitDisplay->setRotation(4);
#else
adafruitDisplay->setRotation(3);
#endif
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(MESHLINK)
@ -166,7 +174,8 @@ bool EInkDisplay::connect()
}
#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_VISION_MASTER_E213) || \
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER)
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \
defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER)
{
// Start HSPI
hspi = new SPIClass(HSPI);
@ -182,7 +191,7 @@ bool EInkDisplay::connect()
// Init GxEPD2
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
#if defined(CROWPANEL_ESP32S3_5_EPAPER)
#if defined(CROWPANEL_ESP32S3_5_EPAPER) || defined(CROWPANEL_ESP32S3_4_EPAPER)
adafruitDisplay->setRotation(0);
#endif
}

Wyświetl plik

@ -68,7 +68,8 @@ class EInkDisplay : public OLEDDisplay
// If display uses HSPI
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER)
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \
defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER)
SPIClass *hspi = NULL;
#endif

Wyświetl plik

@ -1641,6 +1641,11 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
setScreensaverFrames(einkScreensaver);
#endif
LOG_INFO("Turn off screen");
#ifdef ELECROW_ThinkNode_M1
if (digitalRead(PIN_EINK_EN) == HIGH) {
digitalWrite(PIN_EINK_EN, LOW);
}
#endif
dispdev->displayOff();
#ifdef USE_ST7789
SPI1.end();

Wyświetl plik

@ -119,7 +119,7 @@ void tftSetup(void)
#ifdef ARCH_ESP32
tftSleepObserver.observe(&notifyLightSleep);
endSleepObserver.observe(&notifyLightSleepEnd);
xTaskCreatePinnedToCore(tft_task_handler, "tft", 8192, NULL, 1, NULL, 0);
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
#endif
}

Wyświetl plik

@ -262,6 +262,32 @@ void printInfo()
#ifndef PIO_UNIT_TESTING
void setup()
{
#ifdef POWER_CHRG
pinMode(POWER_CHRG, OUTPUT);
digitalWrite(POWER_CHRG, HIGH);
#endif
#if defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
#endif
#ifdef LED_POWER
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, HIGH);
#endif
#ifdef POWER_LED
pinMode(POWER_LED, OUTPUT);
digitalWrite(POWER_LED, HIGH);
#endif
#ifdef USER_LED
pinMode(USER_LED, OUTPUT);
digitalWrite(USER_LED, LOW);
#endif
#if defined(T_DECK)
// GPIO10 manages all peripheral power supplies
// Turn on peripheral power immediately after MUC starts.
@ -325,13 +351,6 @@ void setup()
initDeepSleep();
// power on peripherals
#if defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
// digitalWrite(PIN_POWER_EN1, INPUT);
#endif
#if defined(LORA_TCXO_GPIO)
pinMode(LORA_TCXO_GPIO, OUTPUT);
digitalWrite(LORA_TCXO_GPIO, HIGH);
@ -825,7 +844,9 @@ void setup()
#ifdef ARCH_PORTDUINO
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
// onNetworkConnected there
udpThread->start();
if (config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpThread->start();
}
#endif
#endif
service = new MeshService();
@ -1301,5 +1322,4 @@ void loop()
mainDelay.delay(delayMsec);
}
}
#endif

Wyświetl plik

@ -347,7 +347,7 @@ bool Channels::anyMqttEnabled()
{
#if USERPREFS_EVENT_MODE
// Don't publish messages on the public MQTT broker if we are in event mode
if (mqtt && mqtt.isUsingDefaultServer()) {
if (mqtt && mqtt->isUsingDefaultServer()) {
return false;
}
#endif

Wyświetl plik

@ -161,10 +161,8 @@ void CryptoEngine::hash(uint8_t *bytes, size_t numBytes)
void CryptoEngine::aesSetKey(const uint8_t *key_bytes, size_t key_len)
{
if (aes) {
delete aes;
aes = nullptr;
}
delete aes;
aes = nullptr;
if (key_len != 0) {
aes = new AESSmall256();
aes->setKey(key_bytes, key_len);
@ -225,10 +223,8 @@ void CryptoEngine::decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes
// Generic implementation of AES-CTR encryption.
void CryptoEngine::encryptAESCtr(CryptoKey _key, uint8_t *_nonce, size_t numBytes, uint8_t *bytes)
{
if (ctr) {
delete ctr;
ctr = nullptr;
}
delete ctr;
ctr = nullptr;
if (_key.length == 16)
ctr = new CTR<AES128>();
else

Wyświetl plik

@ -320,7 +320,10 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
}
}
assert(toPhoneQueue.enqueue(p, 0));
if (toPhoneQueue.enqueue(p, 0) == false) {
LOG_CRIT("Failed to queue a packet into toPhoneQueue!");
abort();
}
fromNum++;
}
@ -334,7 +337,10 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
releaseMqttClientProxyMessageToPool(d);
}
assert(toPhoneMqttProxyQueue.enqueue(m, 0));
if (toPhoneMqttProxyQueue.enqueue(m, 0) == false) {
LOG_CRIT("Failed to queue a packet into toPhoneMqttProxyQueue!");
abort();
}
fromNum++;
}
@ -348,7 +354,10 @@ void MeshService::sendClientNotification(meshtastic_ClientNotification *n)
releaseClientNotificationToPool(d);
}
assert(toPhoneClientNotificationQueue.enqueue(n, 0));
if (toPhoneClientNotificationQueue.enqueue(n, 0) == false) {
LOG_CRIT("Failed to queue a notification into toPhoneClientNotificationQueue!");
abort();
}
fromNum++;
}

Wyświetl plik

@ -51,6 +51,10 @@
#include <utility/bonding.h>
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#include <WiFiOTA.h>
#endif
NodeDB *nodeDB = nullptr;
// we have plenty of ram so statically alloc this tempbuf (for now)
@ -624,6 +628,27 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
meshtastic_Config_PositionConfig_PositionFlags_DOP | meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW);
// Set default value for 'Mesh via UDP'
#if HAS_UDP_MULTICAST
#ifdef USERPREFS_NETWORK_ENABLED_PROTOCOLS
config.network.enabled_protocols = USERPREFS_NETWORK_ENABLED_PROTOCOLS;
#else
config.network.enabled_protocols = 1;
#endif
#endif
#ifdef USERPREFS_NETWORK_WIFI_ENABLED
config.network.wifi_enabled = USERPREFS_NETWORK_WIFI_ENABLED;
#endif
#ifdef USERPREFS_NETWORK_WIFI_SSID
strncpy(config.network.wifi_ssid, USERPREFS_NETWORK_WIFI_SSID, sizeof(config.network.wifi_ssid));
#endif
#ifdef USERPREFS_NETWORK_WIFI_PSK
strncpy(config.network.wifi_psk, USERPREFS_NETWORK_WIFI_PSK, sizeof(config.network.wifi_psk));
#endif
#ifdef DISPLAY_FLIP_SCREEN
config.display.flip_screen = true;
#endif
@ -635,6 +660,12 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
config.display.wake_on_tap_or_motion = true;
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::isUpdated()) {
WiFiOTA::recoverConfig(&config.network);
}
#endif
initConfigIntervals();
}
@ -1433,13 +1464,14 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
#if !(MESHTASTIC_EXCLUDE_PKI)
if (p.public_key.size > 0) {
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
LOG_INFO("Public Key set for node, not updating!");
// we copy the key into the incoming packet, to prevent overwrite
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
} else {
LOG_INFO("Update Node Pubkey!");
}
}
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
LOG_INFO("Public Key set for node, not updating!");
// we copy the key into the incoming packet, to prevent overwrite
p.public_key.size = 32;
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
} else if (p.public_key.size > 0) {
LOG_INFO("Update Node Pubkey!");
}
#endif

Wyświetl plik

@ -18,8 +18,10 @@ bool STM32WLE5JCInterface::init()
{
RadioLibInterface::init();
// https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c
// https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c
#if (!defined(_VARIANT_RAK3172_))
setTCXOVoltage(1.7);
#endif
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
@ -42,4 +44,4 @@ bool STM32WLE5JCInterface::init()
return res == RADIOLIB_ERR_NONE;
}
#endif // ARCH_STM32WL
#endif // ARCH_STM32WL

Wyświetl plik

@ -236,6 +236,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_THINKNODE_M2 = 90,
/* Lilygo T-ETH-Elite */
meshtastic_HardwareModel_T_ETH_ELITE = 91,
/* Heltec HRI-3621 industrial probe */
meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */

Wyświetl plik

@ -23,7 +23,7 @@ class UdpMulticastThread : public concurrency::OSThread
void start()
{
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
#if !defined(ARCH_PORTDUINO)
#ifndef ARCH_PORTDUINO
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
#else
@ -59,7 +59,7 @@ class UdpMulticastThread : public concurrency::OSThread
if (!mp || !udp) {
return false;
}
#if !defined(ARCH_PORTDUINO)
#ifndef ARCH_PORTDUINO
if (WiFi.status() != WL_CONNECTED) {
return false;
}

Wyświetl plik

@ -133,7 +133,7 @@ static void onNetworkConnected()
}
#if HAS_UDP_MULTICAST
if (udpThread) {
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpThread->start();
}
#endif

Wyświetl plik

@ -10,6 +10,9 @@
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "BleOta.h"
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#include "WiFiOTA.h"
#endif
#include "Router.h"
#include "configuration.h"
#include "main.h"
@ -194,19 +197,23 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
}
case meshtastic_AdminMessage_reboot_ota_seconds_tag: {
int32_t s = r->reboot_ota_seconds;
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
if (BleOta::getOtaAppVersion().isEmpty()) {
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds", s);
screen->startAlert("Rebooting...");
} else {
#if defined(ARCH_ESP32)
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
if (!BleOta::getOtaAppVersion().isEmpty()) {
screen->startFirmwareUpdateScreen();
BleOta::switchToOtaApp();
LOG_INFO("Reboot to OTA in %d seconds", s);
LOG_INFO("Rebooting to BLE OTA");
}
#else
LOG_INFO("Not on ESP32, scheduling regular reboot in %d seconds", s);
screen->startAlert("Rebooting...");
#endif
#if !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::trySwitchToOTA()) {
screen->startFirmwareUpdateScreen();
WiFiOTA::saveConfig(&config.network);
LOG_INFO("Rebooting to WiFi OTA");
}
#endif
#endif
LOG_INFO("Reboot in %d seconds", s);
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
}

Wyświetl plik

@ -7,7 +7,9 @@
#include "input/SerialKeyboardImpl.h"
#include "input/TrackballInterruptImpl1.h"
#include "input/UpDownInterruptImpl1.h"
#if !MESHTASTIC_EXCLUDE_I2C
#include "input/cardKbI2cImpl.h"
#endif
#include "input/kbMatrixImpl.h"
#endif
#if !MESHTASTIC_EXCLUDE_ADMIN

Wyświetl plik

@ -31,7 +31,7 @@ uint32_t packetSequence = 0;
int32_t RangeTestModule::runOnce()
{
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
/*
Uncomment the preferences below if you want to use the module
@ -130,7 +130,7 @@ void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket &mp)
{
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
if (moduleConfig.range_test.enabled) {

Wyświetl plik

@ -60,7 +60,7 @@
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK)
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial;
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
@ -158,7 +158,7 @@ int32_t SerialModule::runOnce()
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@ -214,7 +214,7 @@ int32_t SerialModule::runOnce()
}
}
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
@ -416,7 +416,8 @@ uint32_t SerialModule::getBaudRate()
*/
void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK)
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;
@ -468,81 +469,83 @@ void SerialModule::processWXSerial()
// Extract the current line
char line[meshtastic_Constants_DATA_PAYLOAD_LEN];
memset(line, '\0', sizeof(line));
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
if (strstr(line, "Wind") != NULL) // we have a wind line
{
gotwind = true;
// Find the positions of "=" signs in the line
char *windDirPos = strstr(line, "WindDir = ");
char *windSpeedPos = strstr(line, "WindSpeed = ");
char *windGustPos = strstr(line, "WindGust = ");
if (lineEnd - lineStart < sizeof(line) - 1) {
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
if (strstr(line, "Wind") != NULL) // we have a wind line
{
gotwind = true;
// Find the positions of "=" signs in the line
char *windDirPos = strstr(line, "WindDir = ");
char *windSpeedPos = strstr(line, "WindSpeed = ");
char *windGustPos = strstr(line, "WindGust = ");
if (windDirPos != NULL) {
// Extract data after "=" for WindDir
strcpy(windDir, windDirPos + 15); // Add 15 to skip "WindDir = "
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
dir_sum_sin += sin(radians);
dir_sum_cos += cos(radians);
dirCount++;
} else if (windSpeedPos != NULL) {
// Extract data after "=" for WindSpeed
strcpy(windVel, windSpeedPos + 15); // Add 15 to skip "WindSpeed = "
float newv = strtof(windVel, nullptr);
velSum += newv;
velCount++;
if (newv < lull || lull == -1)
lull = newv;
if (windDirPos != NULL) {
// Extract data after "=" for WindDir
strlcpy(windDir, windDirPos + 15, sizeof(windDir)); // Add 15 to skip "WindDir = "
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
dir_sum_sin += sin(radians);
dir_sum_cos += cos(radians);
dirCount++;
} else if (windSpeedPos != NULL) {
// Extract data after "=" for WindSpeed
strlcpy(windVel, windSpeedPos + 15, sizeof(windVel)); // Add 15 to skip "WindSpeed = "
float newv = strtof(windVel, nullptr);
velSum += newv;
velCount++;
if (newv < lull || lull == -1)
lull = newv;
} else if (windGustPos != NULL) {
strcpy(windGust, windGustPos + 15); // Add 15 to skip "WindSpeed = "
float newg = strtof(windGust, nullptr);
if (newg > gust)
gust = newg;
}
} else if (windGustPos != NULL) {
strlcpy(windGust, windGustPos + 15, sizeof(windGust)); // Add 15 to skip "WindSpeed = "
float newg = strtof(windGust, nullptr);
if (newg > gust)
gust = newg;
}
// these are also voltage data we care about possibly
} else if (strstr(line, "BatVoltage") != NULL) { // we have a battVoltage line
char *batVoltagePos = strstr(line, "BatVoltage = ");
if (batVoltagePos != NULL) {
strcpy(batVoltage, batVoltagePos + 17); // 18 for ws 80, 17 for ws85
batVoltageF = strtof(batVoltage, nullptr);
break; // last possible data we want so break
}
} else if (strstr(line, "CapVoltage") != NULL) { // we have a cappVoltage line
char *capVoltagePos = strstr(line, "CapVoltage = ");
if (capVoltagePos != NULL) {
strcpy(capVoltage, capVoltagePos + 17); // 18 for ws 80, 17 for ws85
capVoltageF = strtof(capVoltage, nullptr);
}
// GXTS04Temp = 24.4
} else if (strstr(line, "GXTS04Temp") != NULL) { // we have a temperature line
char *tempPos = strstr(line, "GXTS04Temp = ");
if (tempPos != NULL) {
strcpy(temperature, tempPos + 15); // 15 spaces for ws85
temperatureF = strtof(temperature, nullptr);
}
// these are also voltage data we care about possibly
} else if (strstr(line, "BatVoltage") != NULL) { // we have a battVoltage line
char *batVoltagePos = strstr(line, "BatVoltage = ");
if (batVoltagePos != NULL) {
strlcpy(batVoltage, batVoltagePos + 17, sizeof(batVoltage)); // 18 for ws 80, 17 for ws85
batVoltageF = strtof(batVoltage, nullptr);
break; // last possible data we want so break
}
} else if (strstr(line, "CapVoltage") != NULL) { // we have a cappVoltage line
char *capVoltagePos = strstr(line, "CapVoltage = ");
if (capVoltagePos != NULL) {
strlcpy(capVoltage, capVoltagePos + 17, sizeof(capVoltage)); // 18 for ws 80, 17 for ws85
capVoltageF = strtof(capVoltage, nullptr);
}
// GXTS04Temp = 24.4
} else if (strstr(line, "GXTS04Temp") != NULL) { // we have a temperature line
char *tempPos = strstr(line, "GXTS04Temp = ");
if (tempPos != NULL) {
strlcpy(temperature, tempPos + 15, sizeof(temperature)); // 15 spaces for ws85
temperatureF = strtof(temperature, nullptr);
}
} else if (strstr(line, "RainIntSum") != NULL) { // we have a rainsum line
// LOG_INFO(line);
char *pos = strstr(line, "RainIntSum = ");
if (pos != NULL) {
strcpy(rainStr, pos + 17); // 17 spaces for ws85
rainSum = int(strtof(rainStr, nullptr));
}
} else if (strstr(line, "Rain") != NULL) { // we have a rain line
if (strstr(line, "WaveRain") == NULL) { // skip WaveRain lines though.
} else if (strstr(line, "RainIntSum") != NULL) { // we have a rainsum line
// LOG_INFO(line);
char *pos = strstr(line, "Rain = ");
char *pos = strstr(line, "RainIntSum = ");
if (pos != NULL) {
strcpy(rainStr, pos + 17); // 17 spaces for ws85
rain = strtof(rainStr, nullptr);
strlcpy(rainStr, pos + 17, sizeof(rainStr)); // 17 spaces for ws85
rainSum = int(strtof(rainStr, nullptr));
}
} else if (strstr(line, "Rain") != NULL) { // we have a rain line
if (strstr(line, "WaveRain") == NULL) { // skip WaveRain lines though.
// LOG_INFO(line);
char *pos = strstr(line, "Rain = ");
if (pos != NULL) {
strlcpy(rainStr, pos + 17, sizeof(rainStr)); // 17 spaces for ws85
rain = strtof(rainStr, nullptr);
}
}
}
}
// Update lineStart for the next line
lineStart = lineEnd + 1;
// Update lineStart for the next line
lineStart = lineEnd + 1;
}
}
}
break;

Wyświetl plik

@ -98,7 +98,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
// moduleConfig.telemetry.environment_screen_enabled = 1;
// moduleConfig.telemetry.environment_update_interval = 15;
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled ||
ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE)) {
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return disable();
}
@ -107,7 +108,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
// This is the first time the OSThread library has called this function, so do some setup
firstTime = 0;
if (moduleConfig.telemetry.environment_measurement_enabled) {
if (moduleConfig.telemetry.environment_measurement_enabled || ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
LOG_INFO("Environment Telemetry: init");
#ifdef SENSECAP_INDICATOR
result = indicatorSensor.runOnce();
@ -178,7 +179,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
return result == UINT32_MAX ? disable() : setStartDelay();
} else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled) {
if (!moduleConfig.telemetry.environment_measurement_enabled && !ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
return disable();
} else {
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL

Wyświetl plik

@ -3,6 +3,11 @@
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#pragma once
#ifndef ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE
#define ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE 0
#endif
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "NodeDB.h"
#include "ProtobufModule.h"

Wyświetl plik

@ -160,13 +160,11 @@ class AccelerometerThread : public concurrency::OSThread
void clean()
{
isInitialised = false;
if (sensor != nullptr) {
delete sensor;
sensor = nullptr;
}
delete sensor;
sensor = nullptr;
}
};
#endif
#endif
#endif

Wyświetl plik

@ -0,0 +1,92 @@
#include "WiFiOTA.h"
#include "configuration.h"
#include <Preferences.h>
#include <esp_ota_ops.h>
namespace WiFiOTA
{
static const char *nvsNamespace = "ota-wifi";
static const char *appProjectName = "OTA-WiFi";
static bool updated = false;
bool isUpdated()
{
return updated;
}
void initialize()
{
Preferences prefs;
prefs.begin(nvsNamespace);
if (prefs.getBool("updated")) {
LOG_INFO("First boot after OTA update");
updated = true;
prefs.putBool("updated", false);
}
prefs.end();
}
void recoverConfig(meshtastic_Config_NetworkConfig *network)
{
LOG_INFO("Recovering WiFi settings after OTA update");
Preferences prefs;
prefs.begin(nvsNamespace, true);
String ssid = prefs.getString("ssid");
String psk = prefs.getString("psk");
prefs.end();
network->wifi_enabled = true;
strncpy(network->wifi_ssid, ssid.c_str(), sizeof(network->wifi_ssid));
strncpy(network->wifi_psk, psk.c_str(), sizeof(network->wifi_psk));
}
void saveConfig(meshtastic_Config_NetworkConfig *network)
{
LOG_INFO("Saving WiFi settings for upcoming OTA update");
Preferences prefs;
prefs.begin(nvsNamespace);
prefs.putString("ssid", network->wifi_ssid);
prefs.putString("psk", network->wifi_psk);
prefs.putBool("updated", false);
prefs.end();
}
const esp_partition_t *getAppPartition()
{
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
}
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
{
if (esp_ota_get_partition_description(part, app_desc) != ESP_OK)
return false;
if (strcmp(app_desc->project_name, appProjectName) != 0)
return false;
return true;
}
bool trySwitchToOTA()
{
const esp_partition_t *part = getAppPartition();
esp_app_desc_t app_desc;
if (!getAppDesc(part, &app_desc))
return false;
if (esp_ota_set_boot_partition(part) != ESP_OK)
return false;
return true;
}
String getVersion()
{
const esp_partition_t *part = getAppPartition();
esp_app_desc_t app_desc;
if (!getAppDesc(part, &app_desc))
return String();
return String(app_desc.version);
}
} // namespace WiFiOTA

Wyświetl plik

@ -0,0 +1,18 @@
#ifndef WIFIOTA_H
#define WIFIOTA_H
#include "mesh-pb-constants.h"
#include <Arduino.h>
namespace WiFiOTA
{
void initialize();
bool isUpdated();
void recoverConfig(meshtastic_Config_NetworkConfig *network);
void saveConfig(meshtastic_Config_NetworkConfig *network);
bool trySwitchToOTA();
String getVersion();
} // namespace WiFiOTA
#endif // WIFIOTA_H

Wyświetl plik

@ -144,6 +144,8 @@
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
#elif defined(EBYTE_ESP32_S3)
#define HW_VENDOR meshtastic_HardwareModel_EBYTE_ESP32_S3
#elif defined(ELECROW_ThinkNode_M2)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M2
#elif defined(ESP32_S3_PICO)
#define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO
#elif defined(SENSELORA_S3)
@ -178,6 +180,8 @@
#define HW_VENDOR meshtastic_HardwareModel_MESH_TAB
#elif defined(T_ETH_ELITE)
#define HW_VENDOR meshtastic_HardwareModel_T_ETH_ELITE
#elif defined(HELTEC_SENSOR_HUB)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_SENSOR_HUB
#endif
// -----------------------------------------------------------------------------

Wyświetl plik

@ -9,6 +9,8 @@
#include "nimble/NimbleBluetooth.h"
#endif
#include <WiFiOTA.h>
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
@ -107,6 +109,11 @@ void esp32Setup()
randomSeed(seed);
*/
#ifdef POWER_FULL
pinMode(POWER_FULL, INPUT);
pinMode(7, INPUT);
#endif
LOG_DEBUG("Total heap: %d", ESP.getHeapSize());
LOG_DEBUG("Free heap: %d", ESP.getFreeHeap());
LOG_DEBUG("Total PSRAM: %d", ESP.getPsramSize());
@ -139,12 +146,19 @@ void esp32Setup()
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
String BLEOTA = BleOta::getOtaAppVersion();
if (BLEOTA.isEmpty()) {
LOG_INFO("No OTA firmware available");
LOG_INFO("No BLE OTA firmware available");
} else {
LOG_INFO("OTA firmware version %s", BLEOTA.c_str());
LOG_INFO("BLE OTA firmware version %s", BLEOTA.c_str());
}
#else
LOG_INFO("No OTA firmware available");
#endif
#if !MESHTASTIC_EXCLUDE_WIFI
String version = WiFiOTA::getVersion();
if (version.isEmpty()) {
LOG_INFO("No WiFi OTA firmware available");
} else {
LOG_INFO("WiFi OTA firmware version %s", version.c_str());
}
WiFiOTA::initialize();
#endif
// enableModemSleep();

Wyświetl plik

@ -53,6 +53,8 @@
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
#elif defined(ELECROW_ThinkNode_M1)
#define HW_VENDOR meshtastic_HardwareModel_ThinkNode_M1
#elif defined(NANO_G2_ULTRA)
#define HW_VENDOR meshtastic_HardwareModel_NANO_G2_ULTRA
#elif defined(CANARYONE)
@ -75,6 +77,8 @@
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#elif defined(HELTEC_T114)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_NODE_T114
#elif defined(MESHLINK)
#define HW_VENDOR meshtastic_HardwareModel_MESHLINK
#elif defined(SEEED_XIAO_NRF52840_KIT)
#define HW_VENDOR meshtastic_HardwareModel_XIAO_NRF52_KIT
#else
@ -129,4 +133,4 @@
#if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA)
// No serial ports on this board - ONLY use segger in memory console
#define USE_SEGGER
#endif
#endif

Wyświetl plik

@ -235,6 +235,14 @@ void nrf52InitSemiHosting()
void nrf52Setup()
{
#ifdef USB_CHECK
pinMode(USB_CHECK, INPUT);
#endif
#ifdef ADC_V
pinMode(ADC_V, INPUT);
#endif
uint32_t why = NRF_POWER->RESETREAS;
// per
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
@ -275,9 +283,11 @@ void cpuDeepSleep(uint32_t msecToWake)
Wire.end();
#endif
SPI.end();
#if SPI_INTERFACES_COUNT > 1
SPI1.end();
#endif
// This may cause crashes as debug messages continue to flow.
Serial.end();
#ifdef PIN_SERIAL_RX1
Serial1.end();
#endif
@ -315,6 +325,31 @@ void cpuDeepSleep(uint32_t msecToWake)
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
#endif
#ifdef ELECROW_ThinkNode_M1
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
pinMode(pin, OUTPUT);
}
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
digitalWrite(pin, LOW);
}
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
NRF_GPIO->DIRCLR = (1 << pin);
}
#endif
// Sleepy trackers or sensors can low power "sleep"
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
if (msecToWake != portMAX_DELAY &&
@ -333,6 +368,17 @@ void cpuDeepSleep(uint32_t msecToWake)
// FIXME, use system off mode with ram retention for key state?
// FIXME, use non-init RAM per
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
#ifdef ELECROW_ThinkNode_M1
nrf_gpio_cfg_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW;
nrf_gpio_cfg_sense_set(PIN_BUTTON1, sense);
nrf_gpio_cfg_input(PIN_BUTTON2, NRF_GPIO_PIN_PULLUP);
nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW;
nrf_gpio_cfg_sense_set(PIN_BUTTON2, sense1);
#endif
auto ok = sd_power_system_off();
if (ok != NRF_SUCCESS) {
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!");

Wyświetl plik

@ -210,7 +210,10 @@ void portduinoSetup()
}
char serial[9] = {0};
ch341Hal->getSerialString(serial, 8);
std::cout << "Serial " << serial << std::endl;
std::cout << "CH341 Serial " << serial << std::endl;
char product_string[96] = {0};
ch341Hal->getProductString(product_string, 95);
std::cout << "CH341 Product " << product_string << std::endl;
if (strlen(serial) == 8 && settingsStrings[mac_address].length() < 12) {
uint8_t hash[32] = {0};
memcpy(hash, serial, 8);

Wyświetl plik

@ -61,6 +61,12 @@ class Ch341Hal : public RadioLibHal
strncpy(_serial, pinedio.serial_number, len);
}
void getProductString(char *_product_string, size_t len)
{
len = len > 95 ? 95 : len;
strncpy(_product_string, pinedio.product_string, len);
}
void init() override {}
void term() override {}

Wyświetl plik

@ -0,0 +1,198 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 hathach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "LittleFS.h"
#include "stm32wlxx_hal_flash.h"
/**********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
/** This macro is used to suppress compiler messages about a parameter not being used in a function. */
#define LFS_UNUSED(p) (void)((p))
#define STM32WL_PAGE_SIZE (FLASH_PAGE_SIZE)
#define STM32WL_PAGE_COUNT (FLASH_PAGE_NB)
#define STM32WL_FLASH_BASE (FLASH_BASE)
/*
* FLASH_SIZE from stm32wle5xx.h will read the actual FLASH size from the chip.
* FLASH_END_ADDR is calculated from FLASH_SIZE.
* Use the last 28 KiB of the FLASH
*/
#define LFS_FLASH_TOTAL_SIZE (14 * 2048) /* needs to be a multiple of LFS_BLOCK_SIZE */
#define LFS_BLOCK_SIZE (2048)
#define LFS_FLASH_ADDR_END (FLASH_END_ADDR)
#define LFS_FLASH_ADDR_BASE (LFS_FLASH_ADDR_END - LFS_FLASH_TOTAL_SIZE + 1)
#if !CFG_DEBUG
#define _LFS_DBG(fmt, ...)
#else
#define _LFS_DBG(fmt, ...) printf("%s:%d (%s): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__)
#endif
//--------------------------------------------------------------------+
// LFS Disk IO
//--------------------------------------------------------------------+
static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
{
LFS_UNUSED(c);
if (!buffer || !size) {
_LFS_DBG("%s Invalid parameter!\r\n", __func__);
return LFS_ERR_INVAL;
}
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
memcpy(buffer, (void *)address, size);
return LFS_ERR_OK;
}
// Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
HAL_StatusTypeDef hal_rc = HAL_OK;
uint32_t dw_count = size / 8;
uint64_t *bufp = (uint64_t *)buffer;
LFS_UNUSED(c);
_LFS_DBG("Programming %d bytes/%d doublewords at address 0x%08x/block %d, offset %d.", size, dw_count, address, block, off);
if (HAL_FLASH_Unlock() != HAL_OK) {
return LFS_ERR_IO;
}
for (uint32_t i = 0; i < dw_count; i++) {
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
_LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x.\n", address);
HAL_FLASH_Lock();
return LFS_ERR_INVAL;
}
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *bufp);
if (hal_rc != HAL_OK) {
/* Error occurred while writing data in Flash memory.
* User can add here some code to deal with this error.
*/
_LFS_DBG("Program error at (0x%08x), 0x%X, error: 0x%08x\n", address, hal_rc, HAL_FLASH_GetError());
}
address += 8;
bufp += 1;
}
if (HAL_FLASH_Lock() != HAL_OK) {
return LFS_ERR_IO;
}
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
}
// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
{
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE);
HAL_StatusTypeDef hal_rc;
FLASH_EraseInitTypeDef EraseInitStruct = {.TypeErase = FLASH_TYPEERASE_PAGES, .Page = 0, .NbPages = 1};
uint32_t PAGEError = 0;
LFS_UNUSED(c);
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
_LFS_DBG("Wanted to erase out of bound of FLASH: 0x%08x.\n", address);
return LFS_ERR_INVAL;
}
/* calculate the absolute page, i.e. what the ST wants */
EraseInitStruct.Page = (address - STM32WL_FLASH_BASE) / STM32WL_PAGE_SIZE;
_LFS_DBG("Erasing block %d at 0x%08x... ", block, address);
HAL_FLASH_Unlock();
hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
HAL_FLASH_Lock();
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
}
// Sync the state of the underlying block device. Negative error codes
// are propogated to the user.
static int _internal_flash_sync(const struct lfs_config *c)
{
LFS_UNUSED(c);
// write function performs no caching. No need for sync.
return LFS_ERR_OK;
}
static struct lfs_config _InternalFSConfig = {.context = NULL,
.read = _internal_flash_read,
.prog = _internal_flash_prog,
.erase = _internal_flash_erase,
.sync = _internal_flash_sync,
.read_size = LFS_BLOCK_SIZE,
.prog_size = LFS_BLOCK_SIZE,
.block_size = LFS_BLOCK_SIZE,
.block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE,
.lookahead = 128,
.read_buffer = NULL,
.prog_buffer = NULL,
.lookahead_buffer = NULL,
.file_buffer = NULL};
LittleFS InternalFS;
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
LittleFS::LittleFS(void) : STM32_LittleFS(&_InternalFSConfig) {}
bool LittleFS::begin(void)
{
if (FLASH_BASE >= LFS_FLASH_ADDR_BASE) {
/* There is not enough space on this device for a filesystem. */
return false;
}
// failed to mount, erase all pages then format and mount again
if (!STM32_LittleFS::begin()) {
// Erase all pages of internal flash region for Filesystem.
for (uint32_t addr = LFS_FLASH_ADDR_BASE; addr < (LFS_FLASH_ADDR_END + 1); addr += STM32WL_PAGE_SIZE) {
_internal_flash_erase(&_InternalFSConfig, (addr - LFS_FLASH_ADDR_BASE) / STM32WL_PAGE_SIZE);
}
// lfs format
this->format();
// mount again if still failed, give up
if (!STM32_LittleFS::begin())
return false;
}
return true;
}

Wyświetl plik

@ -0,0 +1,41 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 hathach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef INTERNALFILESYSTEM_H_
#define INTERNALFILESYSTEM_H_
#include "STM32_LittleFS.h"
class LittleFS : public STM32_LittleFS
{
public:
LittleFS(void);
// overwrite to also perform low level format (sector erase of whole flash region)
bool begin(void);
};
extern LittleFS InternalFS;
#endif /* INTERNALFILESYSTEM_H_ */

Wyświetl plik

@ -0,0 +1,283 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "STM32_LittleFS.h"
#include <Arduino.h>
#include <string.h>
#define memclr(buffer, size) memset(buffer, 0, size)
#define varclr(_var) memclr(_var, sizeof(*(_var)))
using namespace STM32_LittleFS_Namespace;
//--------------------------------------------------------------------+
// Implementation
//--------------------------------------------------------------------+
STM32_LittleFS::STM32_LittleFS(void) : STM32_LittleFS(NULL) {}
STM32_LittleFS::STM32_LittleFS(struct lfs_config *cfg)
{
varclr(&_lfs);
_lfs_cfg = cfg;
_mounted = false;
}
STM32_LittleFS::~STM32_LittleFS() {}
// Initialize and mount the file system
// Return true if mounted successfully else probably corrupted.
// User should format the disk and try again
bool STM32_LittleFS::begin(struct lfs_config *cfg)
{
_lockFS();
bool ret;
// not a loop, just an quick way to short-circuit on error
do {
if (_mounted) {
ret = true;
break;
}
if (cfg) {
_lfs_cfg = cfg;
}
if (nullptr == _lfs_cfg) {
ret = false;
break;
}
// actually attempt to mount, and log error if one occurs
int err = lfs_mount(&_lfs, _lfs_cfg);
PRINT_LFS_ERR(err);
_mounted = (err == LFS_ERR_OK);
ret = _mounted;
} while (0);
_unlockFS();
return ret;
}
// Tear down and unmount file system
void STM32_LittleFS::end(void)
{
_lockFS();
if (_mounted) {
_mounted = false;
int err = lfs_unmount(&_lfs);
PRINT_LFS_ERR(err);
(void)err;
}
_unlockFS();
}
bool STM32_LittleFS::format(void)
{
_lockFS();
int err = LFS_ERR_OK;
bool attemptMount = _mounted;
// not a loop, just an quick way to short-circuit on error
do {
// if already mounted: umount first -> format -> remount
if (_mounted) {
_mounted = false;
err = lfs_unmount(&_lfs);
if (LFS_ERR_OK != err) {
PRINT_LFS_ERR(err);
break;
}
}
err = lfs_format(&_lfs, _lfs_cfg);
if (LFS_ERR_OK != err) {
PRINT_LFS_ERR(err);
break;
}
if (attemptMount) {
err = lfs_mount(&_lfs, _lfs_cfg);
if (LFS_ERR_OK != err) {
PRINT_LFS_ERR(err);
break;
}
_mounted = true;
}
// success!
} while (0);
_unlockFS();
return LFS_ERR_OK == err;
}
// Open a file or folder
STM32_LittleFS_Namespace::File STM32_LittleFS::open(char const *filepath, uint8_t mode)
{
// No lock is required here ... the File() object will synchronize with the mutex provided
return STM32_LittleFS_Namespace::File(filepath, mode, *this);
}
// Check if file or folder exists
bool STM32_LittleFS::exists(char const *filepath)
{
struct lfs_info info;
_lockFS();
bool ret = (0 == lfs_stat(&_lfs, filepath, &info));
_unlockFS();
return ret;
}
// Create a directory, create intermediate parent if needed
bool STM32_LittleFS::mkdir(char const *filepath)
{
bool ret = true;
const char *slash = filepath;
if (slash[0] == '/')
slash++; // skip root '/'
_lockFS();
// make intermediate parent directory(ies)
while (NULL != (slash = strchr(slash, '/'))) {
char parent[slash - filepath + 1] = {0};
memcpy(parent, filepath, slash - filepath);
int rc = lfs_mkdir(&_lfs, parent);
if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) {
PRINT_LFS_ERR(rc);
ret = false;
break;
}
slash++;
}
// make the final requested directory
if (ret) {
int rc = lfs_mkdir(&_lfs, filepath);
if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) {
PRINT_LFS_ERR(rc);
ret = false;
}
}
_unlockFS();
return ret;
}
// Remove a file
bool STM32_LittleFS::remove(char const *filepath)
{
_lockFS();
int err = lfs_remove(&_lfs, filepath);
PRINT_LFS_ERR(err);
_unlockFS();
return LFS_ERR_OK == err;
}
// Rename a file
bool STM32_LittleFS::rename(char const *oldfilepath, char const *newfilepath)
{
_lockFS();
int err = lfs_rename(&_lfs, oldfilepath, newfilepath);
PRINT_LFS_ERR(err);
_unlockFS();
return LFS_ERR_OK == err;
}
// Remove a folder
bool STM32_LittleFS::rmdir(char const *filepath)
{
_lockFS();
int err = lfs_remove(&_lfs, filepath);
PRINT_LFS_ERR(err);
_unlockFS();
return LFS_ERR_OK == err;
}
// Remove a folder recursively
bool STM32_LittleFS::rmdir_r(char const *filepath)
{
/* lfs is modified to remove non-empty folder,
According to below issue, comment these 2 line won't corrupt filesystem
at least when using LFS v1. If moving to LFS v2, see tracked issue
to see if issues (such as the orphans in threaded linked list) are resolved.
https://github.com/ARMmbed/littlefs/issues/43
*/
_lockFS();
int err = lfs_remove(&_lfs, filepath);
PRINT_LFS_ERR(err);
_unlockFS();
return LFS_ERR_OK == err;
}
//------------- Debug -------------//
#if CFG_DEBUG
const char *dbg_strerr_lfs(int32_t err)
{
switch (err) {
case LFS_ERR_OK:
return "LFS_ERR_OK";
case LFS_ERR_IO:
return "LFS_ERR_IO";
case LFS_ERR_CORRUPT:
return "LFS_ERR_CORRUPT";
case LFS_ERR_NOENT:
return "LFS_ERR_NOENT";
case LFS_ERR_EXIST:
return "LFS_ERR_EXIST";
case LFS_ERR_NOTDIR:
return "LFS_ERR_NOTDIR";
case LFS_ERR_ISDIR:
return "LFS_ERR_ISDIR";
case LFS_ERR_NOTEMPTY:
return "LFS_ERR_NOTEMPTY";
case LFS_ERR_BADF:
return "LFS_ERR_BADF";
case LFS_ERR_INVAL:
return "LFS_ERR_INVAL";
case LFS_ERR_NOSPC:
return "LFS_ERR_NOSPC";
case LFS_ERR_NOMEM:
return "LFS_ERR_NOMEM";
default:
static char errcode[10];
sprintf(errcode, "%ld", err);
return errcode;
}
return NULL;
}
#endif

Wyświetl plik

@ -0,0 +1,107 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef STM32_LITTLEFS_H_
#define STM32_LITTLEFS_H_
#include <Stream.h>
// Internal Flash uses ARM Little FileSystem
// https://github.com/ARMmbed/littlefs
#include "../../freertosinc.h" // tied to FreeRTOS for serialization
#include "STM32_LittleFS_File.h"
#include "littlefs/lfs.h"
class STM32_LittleFS
{
public:
STM32_LittleFS(void);
STM32_LittleFS(struct lfs_config *cfg);
virtual ~STM32_LittleFS();
bool begin(struct lfs_config *cfg = NULL);
void end(void);
// Open the specified file/directory with the supplied mode (e.g. read or
// write, etc). Returns a File object for interacting with the file.
// Note that currently only one file can be open at a time.
STM32_LittleFS_Namespace::File open(char const *filename, uint8_t mode = STM32_LittleFS_Namespace::FILE_O_READ);
// Methods to determine if the requested file path exists.
bool exists(char const *filepath);
// Create the requested directory hierarchy--if intermediate directories
// do not exist they will be created.
bool mkdir(char const *filepath);
// Delete the file.
bool remove(char const *filepath);
// Rename the file.
bool rename(char const *oldfilepath, char const *newfilepath);
// Delete a folder (must be empty)
bool rmdir(char const *filepath);
// Delete a folder (recursively)
bool rmdir_r(char const *filepath);
// format file system
bool format(void);
/*------------------------------------------------------------------*/
/* INTERNAL USAGE ONLY
* Although declare as public, it is meant to be invoked by internal
* code. User should not call these directly
*------------------------------------------------------------------*/
lfs_t *_getFS(void) { return &_lfs; }
void _lockFS(void)
{ /* no-op */
}
void _unlockFS(void)
{ /* no-op */
}
protected:
bool _mounted;
struct lfs_config *_lfs_cfg;
lfs_t _lfs;
};
#if !CFG_DEBUG
#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, NULL)
#define PRINT_LFS_ERR(_err)
#else
#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, dbg_strerr_lfs)
#define PRINT_LFS_ERR(_err) \
do { \
if (_err) { \
printf("%s:%d, LFS error: %d\n", __FILE__, __LINE__, _err); \
} \
} while (0) // LFS_ERR are of type int, VERIFY_MESS expects long_int
const char *dbg_strerr_lfs(int32_t err);
#endif
#endif /* STM32_LITTLEFS_H_ */

Wyświetl plik

@ -0,0 +1,394 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "STM32_LittleFS.h"
#include <Arduino.h>
#define rtos_malloc malloc
#define rtos_free free
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
using namespace STM32_LittleFS_Namespace;
File::File(STM32_LittleFS &fs)
{
_fs = &fs;
_is_dir = false;
_name[0] = 0;
_name[LFS_NAME_MAX] = 0;
_dir_path = NULL;
_dir = NULL;
_file = NULL;
}
File::File(char const *filename, uint8_t mode, STM32_LittleFS &fs) : File(fs)
{
// public constructor calls public API open(), which will obtain the mutex
this->open(filename, mode);
}
bool File::_open_file(char const *filepath, uint8_t mode)
{
int flags = (mode == FILE_O_READ) ? LFS_O_RDONLY : (mode == FILE_O_WRITE) ? (LFS_O_RDWR | LFS_O_CREAT) : 0;
if (flags) {
_file = (lfs_file_t *)rtos_malloc(sizeof(lfs_file_t));
if (!_file)
return false;
int rc = lfs_file_open(_fs->_getFS(), _file, filepath, flags);
if (rc) {
// failed to open
PRINT_LFS_ERR(rc);
// free memory
rtos_free(_file);
_file = NULL;
return false;
}
// move to end of file
if (mode == FILE_O_WRITE)
lfs_file_seek(_fs->_getFS(), _file, 0, LFS_SEEK_END);
_is_dir = false;
}
return true;
}
bool File::_open_dir(char const *filepath)
{
_dir = (lfs_dir_t *)rtos_malloc(sizeof(lfs_dir_t));
if (!_dir)
return false;
int rc = lfs_dir_open(_fs->_getFS(), _dir, filepath);
if (rc) {
// failed to open
PRINT_LFS_ERR(rc);
// free memory
rtos_free(_dir);
_dir = NULL;
return false;
}
_is_dir = true;
_dir_path = (char *)rtos_malloc(strlen(filepath) + 1);
strcpy(_dir_path, filepath);
return true;
}
bool File::open(char const *filepath, uint8_t mode)
{
bool ret = false;
_fs->_lockFS();
ret = this->_open(filepath, mode);
_fs->_unlockFS();
return ret;
}
bool File::_open(char const *filepath, uint8_t mode)
{
bool ret = false;
// close if currently opened
if (this->isOpen())
_close();
struct lfs_info info;
int rc = lfs_stat(_fs->_getFS(), filepath, &info);
if (LFS_ERR_OK == rc) {
// file existed, open file or directory accordingly
ret = (info.type == LFS_TYPE_REG) ? _open_file(filepath, mode) : _open_dir(filepath);
} else if (LFS_ERR_NOENT == rc) {
// file not existed, only proceed with FILE_O_WRITE mode
if (mode == FILE_O_WRITE)
ret = _open_file(filepath, mode);
} else {
PRINT_LFS_ERR(rc);
}
// save bare file name
if (ret) {
char const *splash = strrchr(filepath, '/');
strncpy(_name, splash ? (splash + 1) : filepath, LFS_NAME_MAX);
}
return ret;
}
size_t File::write(uint8_t ch)
{
return write(&ch, 1);
}
size_t File::write(uint8_t const *buf, size_t size)
{
lfs_ssize_t wrcount = 0;
_fs->_lockFS();
if (!this->_is_dir) {
wrcount = lfs_file_write(_fs->_getFS(), _file, buf, size);
if (wrcount < 0) {
wrcount = 0;
}
}
_fs->_unlockFS();
return wrcount;
}
int File::read(void)
{
// this thin wrapper relies on called function to synchronize
int ret = -1;
uint8_t ch;
if (read(&ch, 1) > 0) {
ret = static_cast<int>(ch);
}
return ret;
}
int File::read(void *buf, uint16_t nbyte)
{
int ret = 0;
_fs->_lockFS();
if (!this->_is_dir) {
ret = lfs_file_read(_fs->_getFS(), _file, buf, nbyte);
}
_fs->_unlockFS();
return ret;
}
int File::peek(void)
{
int ret = -1;
_fs->_lockFS();
if (!this->_is_dir) {
uint32_t pos = lfs_file_tell(_fs->_getFS(), _file);
uint8_t ch = 0;
if (lfs_file_read(_fs->_getFS(), _file, &ch, 1) > 0) {
ret = static_cast<int>(ch);
}
(void)lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET);
}
_fs->_unlockFS();
return ret;
}
int File::available(void)
{
int ret = 0;
_fs->_lockFS();
if (!this->_is_dir) {
uint32_t size = lfs_file_size(_fs->_getFS(), _file);
uint32_t pos = lfs_file_tell(_fs->_getFS(), _file);
ret = size - pos;
}
_fs->_unlockFS();
return ret;
}
bool File::seek(uint32_t pos)
{
bool ret = false;
_fs->_lockFS();
if (!this->_is_dir) {
ret = lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET) >= 0;
}
_fs->_unlockFS();
return ret;
}
uint32_t File::position(void)
{
uint32_t ret = 0;
_fs->_lockFS();
if (!this->_is_dir) {
ret = lfs_file_tell(_fs->_getFS(), _file);
}
_fs->_unlockFS();
return ret;
}
uint32_t File::size(void)
{
uint32_t ret = 0;
_fs->_lockFS();
if (!this->_is_dir) {
ret = lfs_file_size(_fs->_getFS(), _file);
}
_fs->_unlockFS();
return ret;
}
bool File::truncate(uint32_t pos)
{
int32_t ret = LFS_ERR_ISDIR;
_fs->_lockFS();
if (!this->_is_dir) {
ret = lfs_file_truncate(_fs->_getFS(), _file, pos);
}
_fs->_unlockFS();
return (ret == 0);
}
bool File::truncate(void)
{
int32_t ret = LFS_ERR_ISDIR;
uint32_t pos;
_fs->_lockFS();
if (!this->_is_dir) {
pos = lfs_file_tell(_fs->_getFS(), _file);
ret = lfs_file_truncate(_fs->_getFS(), _file, pos);
}
_fs->_unlockFS();
return (ret == 0);
}
void File::flush(void)
{
_fs->_lockFS();
if (!this->_is_dir) {
lfs_file_sync(_fs->_getFS(), _file);
}
_fs->_unlockFS();
return;
}
void File::close(void)
{
_fs->_lockFS();
this->_close();
_fs->_unlockFS();
}
void File::_close(void)
{
if (this->isOpen()) {
if (this->_is_dir) {
lfs_dir_close(_fs->_getFS(), _dir);
rtos_free(_dir);
_dir = NULL;
if (this->_dir_path)
rtos_free(_dir_path);
_dir_path = NULL;
} else {
lfs_file_close(this->_fs->_getFS(), _file);
rtos_free(_file);
_file = NULL;
}
}
}
File::operator bool(void)
{
return isOpen();
}
bool File::isOpen(void)
{
return (_file != NULL) || (_dir != NULL);
}
// WARNING -- although marked as `const`, the values pointed
// to may change. For example, if the same File
// object has `open()` called with a different
// file or directory name, this same pointer will
// suddenly (unexpectedly?) have different values.
char const *File::name(void)
{
return this->_name;
}
bool File::isDirectory(void)
{
return this->_is_dir;
}
File File::openNextFile(uint8_t mode)
{
_fs->_lockFS();
File ret(*_fs);
if (this->_is_dir) {
struct lfs_info info;
int rc;
// lfs_dir_read returns 0 when reaching end of directory, 1 if found an entry
// Skip the "." and ".." entries ...
do {
rc = lfs_dir_read(_fs->_getFS(), _dir, &info);
} while (rc == 1 && (!strcmp(".", info.name) || !strcmp("..", info.name)));
if (rc == 1) {
// string cat name with current folder
char filepath[strlen(_dir_path) + 1 + strlen(info.name) + 1]; // potential for significant stack usage
strcpy(filepath, _dir_path);
if (!(_dir_path[0] == '/' && _dir_path[1] == 0))
strcat(filepath, "/"); // only add '/' if cwd is not root
strcat(filepath, info.name);
(void)ret._open(filepath, mode); // return value is ignored ... caller is expected to check isOpened()
} else if (rc < 0) {
PRINT_LFS_ERR(rc);
}
}
_fs->_unlockFS();
return ret;
}
void File::rewindDirectory(void)
{
_fs->_lockFS();
if (this->_is_dir) {
lfs_dir_rewind(_fs->_getFS(), _dir);
}
_fs->_unlockFS();
}

Wyświetl plik

@ -0,0 +1,108 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef STM32_LITTLEFS_FILE_H_
#define STM32_LITTLEFS_FILE_H_
#include "littlefs/lfs.h"
// Forward declaration
class STM32_LittleFS;
namespace STM32_LittleFS_Namespace
{
// avoid conflict with other FileSystem FILE_READ/FILE_WRITE
enum {
FILE_O_READ = 0,
FILE_O_WRITE = 1,
};
class File : public Stream
{
public:
File(STM32_LittleFS &fs);
File(char const *filename, uint8_t mode, STM32_LittleFS &fs);
public:
bool open(char const *filename, uint8_t mode);
//------------- Stream API -------------//
virtual size_t write(uint8_t ch);
virtual size_t write(uint8_t const *buf, size_t size);
size_t write(const char *str)
{
if (str == NULL)
return 0;
return write((const uint8_t *)str, strlen(str));
}
size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); }
virtual int read(void);
int read(void *buf, uint16_t nbyte);
virtual int peek(void);
virtual int available(void);
virtual void flush(void);
bool seek(uint32_t pos);
uint32_t position(void);
uint32_t size(void);
bool truncate(uint32_t pos);
bool truncate(void);
void close(void);
operator bool(void);
bool isOpen(void);
char const *name(void);
bool isDirectory(void);
File openNextFile(uint8_t mode = FILE_O_READ);
void rewindDirectory(void);
private:
STM32_LittleFS *_fs;
bool _is_dir;
union {
lfs_file_t *_file;
lfs_dir_t *_dir;
};
char *_dir_path;
char _name[LFS_NAME_MAX + 1];
bool _open(char const *filepath, uint8_t mode);
bool _open_file(char const *filepath, uint8_t mode);
bool _open_dir(char const *filepath);
void _close(void);
};
} // namespace STM32_LittleFS_Namespace
#endif /* STM32_LITTLEFS_FILE_H_ */

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,476 @@
/*
* The little filesystem
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LFS_H
#define LFS_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/// Version info ///
// Software library version
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS_VERSION 0x00010006
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
// Version of On-disk data structures
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS_DISK_VERSION 0x00010001
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
/// Definitions ///
// Type definitions
typedef uint32_t lfs_size_t;
typedef uint32_t lfs_off_t;
typedef int32_t lfs_ssize_t;
typedef int32_t lfs_soff_t;
typedef uint32_t lfs_block_t;
// Max name size in bytes
#ifndef LFS_NAME_MAX
#define LFS_NAME_MAX 255
#endif
// Possible error codes, these are negative to allow
// valid positive return values
enum lfs_error {
LFS_ERR_OK = 0, // No error
LFS_ERR_IO = -5, // Error during device operation
LFS_ERR_CORRUPT = -52, // Corrupted
LFS_ERR_NOENT = -2, // No directory entry
LFS_ERR_EXIST = -17, // Entry already exists
LFS_ERR_NOTDIR = -20, // Entry is not a dir
LFS_ERR_ISDIR = -21, // Entry is a dir
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
LFS_ERR_BADF = -9, // Bad file number
LFS_ERR_INVAL = -22, // Invalid parameter
LFS_ERR_NOSPC = -28, // No space left on device
LFS_ERR_NOMEM = -12, // No more memory available
};
// File types
enum lfs_type {
LFS_TYPE_REG = 0x11,
LFS_TYPE_DIR = 0x22,
LFS_TYPE_SUPERBLOCK = 0x2e,
};
// File open flags
enum lfs_open_flags {
// open flags
LFS_O_RDONLY = 1, // Open a file as read only
LFS_O_WRONLY = 2, // Open a file as write only
LFS_O_RDWR = 3, // Open a file as read and write
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS_O_APPEND = 0x0800, // Move to end of file on every write
// internally used flags
LFS_F_DIRTY = 0x10000, // File does not match storage
LFS_F_WRITING = 0x20000, // File has been written since last flush
LFS_F_READING = 0x40000, // File has been read since last flush
LFS_F_ERRED = 0x80000, // An error occured during write
};
// File seek flags
enum lfs_whence_flags {
LFS_SEEK_SET = 0, // Seek relative to an absolute position
LFS_SEEK_CUR = 1, // Seek relative to the current file position
LFS_SEEK_END = 2, // Seek relative to the end of the file
};
// Configuration provided during initialization of the littlefs
struct lfs_config {
// Opaque user provided context that can be used to pass
// information to the block device operations
void *context;
// Read a region in a block. Negative error codes are propogated
// to the user.
int (*read)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
// Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs_config *c, lfs_block_t block);
// Sync the state of the underlying block device. Negative error codes
// are propogated to the user.
int (*sync)(const struct lfs_config *c);
// Minimum size of a block read. This determines the size of read buffers.
// This may be larger than the physical read size to improve performance
// by caching more of the block device.
lfs_size_t read_size;
// Minimum size of a block program. This determines the size of program
// buffers. This may be larger than the physical program size to improve
// performance by caching more of the block device.
// Must be a multiple of the read size.
lfs_size_t prog_size;
// Size of an erasable block. This does not impact ram consumption and
// may be larger than the physical erase size. However, this should be
// kept small as each file currently takes up an entire block.
// Must be a multiple of the program size.
lfs_size_t block_size;
// Number of erasable blocks on the device.
lfs_size_t block_count;
// Number of blocks to lookahead during block allocation. A larger
// lookahead reduces the number of passes required to allocate a block.
// The lookahead buffer requires only 1 bit per block so it can be quite
// large with little ram impact. Should be a multiple of 32.
lfs_size_t lookahead;
// Optional, statically allocated read buffer. Must be read sized.
void *read_buffer;
// Optional, statically allocated program buffer. Must be program sized.
void *prog_buffer;
// Optional, statically allocated lookahead buffer. Must be 1 bit per
// lookahead block.
void *lookahead_buffer;
// Optional, statically allocated buffer for files. Must be program sized.
// If enabled, only one file may be opened at a time.
void *file_buffer;
};
// Optional configuration provided during lfs_file_opencfg
struct lfs_file_config {
// Optional, statically allocated buffer for files. Must be program sized.
// If NULL, malloc will be used by default.
void *buffer;
};
// File info structure
struct lfs_info {
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
uint8_t type;
// Size of the file, only valid for REG files
lfs_size_t size;
// Name of the file stored as a null-terminated string
char name[LFS_NAME_MAX + 1];
};
/// littlefs data structures ///
typedef struct lfs_entry {
lfs_off_t off;
struct lfs_disk_entry {
uint8_t type;
uint8_t elen;
uint8_t alen;
uint8_t nlen;
union {
struct {
lfs_block_t head;
lfs_size_t size;
} file;
lfs_block_t dir[2];
} u;
} d;
} lfs_entry_t;
typedef struct lfs_cache {
lfs_block_t block;
lfs_off_t off;
uint8_t *buffer;
} lfs_cache_t;
typedef struct lfs_file {
struct lfs_file *next;
lfs_block_t pair[2];
lfs_off_t poff;
lfs_block_t head;
lfs_size_t size;
const struct lfs_file_config *cfg;
uint32_t flags;
lfs_off_t pos;
lfs_block_t block;
lfs_off_t off;
lfs_cache_t cache;
} lfs_file_t;
typedef struct lfs_dir {
struct lfs_dir *next;
lfs_block_t pair[2];
lfs_off_t off;
lfs_block_t head[2];
lfs_off_t pos;
struct lfs_disk_dir {
uint32_t rev;
lfs_size_t size;
lfs_block_t tail[2];
} d;
} lfs_dir_t;
typedef struct lfs_superblock {
lfs_off_t off;
struct lfs_disk_superblock {
uint8_t type;
uint8_t elen;
uint8_t alen;
uint8_t nlen;
lfs_block_t root[2];
uint32_t block_size;
uint32_t block_count;
uint32_t version;
char magic[8];
} d;
} lfs_superblock_t;
typedef struct lfs_free {
lfs_block_t off;
lfs_block_t size;
lfs_block_t i;
lfs_block_t ack;
uint32_t *buffer;
} lfs_free_t;
// The littlefs type
typedef struct lfs {
const struct lfs_config *cfg;
lfs_block_t root[2];
lfs_file_t *files;
lfs_dir_t *dirs;
lfs_cache_t rcache;
lfs_cache_t pcache;
lfs_free_t free;
bool deorphaned;
} lfs_t;
/// Filesystem functions ///
// Format a block device with the littlefs
//
// Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
// Mounts a littlefs
//
// Requires a littlefs object and config struct. Multiple filesystems
// may be mounted simultaneously with multiple littlefs objects. Both
// lfs and config must be allocated while mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
// Unmounts a littlefs
//
// Does nothing besides releasing any allocated resources.
// Returns a negative error code on failure.
int lfs_unmount(lfs_t *lfs);
/// General operations ///
// Removes a file or directory
//
// If removing a directory, the directory must be empty.
// Returns a negative error code on failure.
int lfs_remove(lfs_t *lfs, const char *path);
// Rename or move a file or directory
//
// If the destination exists, it must match the source in type.
// If the destination is a directory, the directory must be empty.
//
// Returns a negative error code on failure.
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
// Find info about a file or directory
//
// Fills out the info structure, based on the specified file or directory.
// Returns a negative error code on failure.
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
/// File operations ///
// Open a file
//
// The mode that the file is opened in is determined by the flags, which
// are values from the enum lfs_open_flags that are bitwise-ored together.
//
// Returns a negative error code on failure.
int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags);
// Open a file with extra configuration
//
// The mode that the file is opened in is determined by the flags, which
// are values from the enum lfs_open_flags that are bitwise-ored together.
//
// The config struct provides additional config options per file as described
// above. The config struct must be allocated while the file is open, and the
// config struct must be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, const char *path, int flags, const struct lfs_file_config *config);
// Close a file
//
// Any pending writes are written out to storage as though
// sync had been called and releases any allocated resources.
//
// Returns a negative error code on failure.
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
// Synchronize a file on storage
//
// Any pending writes are written out to storage.
// Returns a negative error code on failure.
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
// Read data from file
//
// Takes a buffer and size indicating where to store the read data.
// Returns the number of bytes read, or a negative error code on failure.
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, void *buffer, lfs_size_t size);
// Write data to file
//
// Takes a buffer and size indicating the data to write. The file will not
// actually be updated on the storage until either sync or close is called.
//
// Returns the number of bytes written, or a negative error code on failure.
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, const void *buffer, lfs_size_t size);
// Change the position of the file
//
// The change in position is determined by the offset and whence flag.
// Returns the old position of the file, or a negative error code on failure.
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, lfs_soff_t off, int whence);
// Truncates the size of the file to the specified size
//
// Returns a negative error code on failure.
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
// Return the position of the file
//
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
// Returns the position of the file, or a negative error code on failure.
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
// Change the position of the file to the beginning of the file
//
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
// Returns a negative error code on failure.
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
// Return the size of the file
//
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
// Returns the size of the file, or a negative error code on failure.
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
/// Directory operations ///
// Create a directory
//
// Returns a negative error code on failure.
int lfs_mkdir(lfs_t *lfs, const char *path);
// Open a directory
//
// Once open a directory can be used with read to iterate over files.
// Returns a negative error code on failure.
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
// Close a directory
//
// Releases any allocated resources.
// Returns a negative error code on failure.
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
// Read an entry in the directory
//
// Fills out the info structure, based on the specified file or directory.
// Returns a negative error code on failure.
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
// Change the position of the directory
//
// The new off must be a value previous returned from tell and specifies
// an absolute offset in the directory seek.
//
// Returns a negative error code on failure.
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
// Return the position of the directory
//
// The returned offset is only meant to be consumed by seek and may not make
// sense, but does indicate the current position in the directory iteration.
//
// Returns the position of the directory, or a negative error code on failure.
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
// Change the position of the directory to the beginning of the directory
//
// Returns a negative error code on failure.
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
/// Miscellaneous littlefs specific operations ///
// Traverse through all blocks in use by the filesystem
//
// The provided callback will be called with each block address that is
// currently in use by the filesystem. This can be used to determine which
// blocks are in use or how much of the storage is available.
//
// Returns a negative error code on failure.
int lfs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data);
// Prunes any recoverable errors that may have occured in the filesystem
//
// Not needed to be called by user unless an operation is interrupted
// but the filesystem is still mounted. This is already called on first
// allocation.
//
// Returns a negative error code on failure.
int lfs_deorphan(lfs_t *lfs);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

Wyświetl plik

@ -0,0 +1,28 @@
/*
* lfs util functions
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "lfs_util.h"
// Only compile if user does not provide custom config
#ifndef LFS_CONFIG
// Software CRC implementation with small lookup table
void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size)
{
static const uint32_t rtable[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
};
const uint8_t *data = buffer;
for (size_t i = 0; i < size; i++) {
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf];
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf];
}
}
#endif

Wyświetl plik

@ -0,0 +1,199 @@
/*
* lfs utility functions
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LFS_UTIL_H
#define LFS_UTIL_H
// Users can override lfs_util.h with their own configuration by defining
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
//
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
// provided by the config file. To start I would suggest copying lfs_util.h and
// modifying as needed.
#ifdef LFS_CONFIG
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x
#include LFS_STRINGIZE(LFS_CONFIG)
#else
// System includes
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#ifndef LFS_NO_MALLOC
#include <stdlib.h>
#endif
#ifndef LFS_NO_ASSERT
#include <assert.h>
#endif
#if !CFG_DEBUG
#define LFS_NO_DEBUG
#define LFS_NO_WARN
#define LFS_NO_ERROR
#endif
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Macros, may be replaced by system specific wrappers. Arguments to these
// macros must not have side-effects as the macros can be removed for a smaller
// code footprint
// Logging functions
#ifndef LFS_NO_DEBUG
#define LFS_DEBUG(fmt, ...) printf("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
#define LFS_DEBUG(fmt, ...)
#endif
#ifndef LFS_NO_WARN
#define LFS_WARN(fmt, ...) printf("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
#define LFS_WARN(fmt, ...)
#endif
#ifndef LFS_NO_ERROR
#define LFS_ERROR(fmt, ...) printf("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
#define LFS_ERROR(fmt, ...)
#endif
// Runtime assertions
#ifndef LFS_NO_ASSERT
#define LFS_ASSERT(test) assert(test)
#else
#define LFS_ASSERT(test)
#endif
// Builtin functions, these may be replaced by more efficient
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
// expensive basic C implementation for debugging purposes
// Min/max functions for unsigned 32-bit numbers
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
{
return (a > b) ? a : b;
}
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
{
return (a < b) ? a : b;
}
// Find the next smallest power of 2 less than or equal to a
static inline uint32_t lfs_npw2(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return 32 - __builtin_clz(a - 1);
#else
uint32_t r = 0;
uint32_t s;
a -= 1;
s = (a > 0xffff) << 4;
a >>= s;
r |= s;
s = (a > 0xff) << 3;
a >>= s;
r |= s;
s = (a > 0xf) << 2;
a >>= s;
r |= s;
s = (a > 0x3) << 1;
a >>= s;
r |= s;
return (r | (a >> 1)) + 1;
#endif
}
// Count the number of trailing binary zeros in a
// lfs_ctz(0) may be undefined
static inline uint32_t lfs_ctz(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
return __builtin_ctz(a);
#else
return lfs_npw2((a & -a) + 1) - 1;
#endif
}
// Count the number of binary ones in a
static inline uint32_t lfs_popc(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return __builtin_popcount(a);
#else
a = a - ((a >> 1) & 0x55555555);
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
#endif
}
// Find the sequence comparison of a and b, this is the distance
// between a and b ignoring overflow
static inline int lfs_scmp(uint32_t a, uint32_t b)
{
return (int)(unsigned)(a - b);
}
// Convert from 32-bit little-endian to native order
static inline uint32_t lfs_fromle32(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && ((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
return a;
#elif !defined(LFS_NO_INTRINSICS) && \
((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
return __builtin_bswap32(a);
#else
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) | (((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
#endif
}
// Convert to 32-bit little-endian from native order
static inline uint32_t lfs_tole32(uint32_t a)
{
return lfs_fromle32(a);
}
// Calculate CRC-32 with polynomial = 0x04c11db7
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
// Allocate memory, only used if buffers are not provided to littlefs
static inline void *lfs_malloc(size_t size)
{
#ifndef LFS_NO_MALLOC
return malloc(size);
#else
(void)size;
return NULL;
#endif
}
// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs_free(void *p)
{
#ifndef LFS_NO_MALLOC
free(p);
#else
(void)p;
#endif
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
#endif

Wyświetl plik

@ -84,6 +84,11 @@ class Power : private concurrency::OSThread
void setStatusHandler(meshtastic::PowerStatus *handler) { statusHandler = handler; }
const uint16_t OCV[11] = {OCV_ARRAY};
#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG)
uint8_t low_voltage_counter_led3;
int power_num = 0;
#endif
protected:
meshtastic::PowerStatus *statusHandler;

Wyświetl plik

@ -32,6 +32,8 @@ void powerCommandsCheck()
delete screen;
LOG_DEBUG("final reboot!");
reboot();
#elif defined(ARCH_STM32WL)
HAL_NVIC_SystemReset();
#else
rebootAtMsec = -1;
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");

Wyświetl plik

@ -228,6 +228,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN
}
#ifdef PIN_POWER_EN
digitalWrite(PIN_POWER_EN, LOW);
pinMode(PIN_POWER_EN, INPUT); // power off peripherals
// pinMode(PIN_POWER_EN1, INPUT_PULLDOWN);
#endif

Wyświetl plik

@ -40,5 +40,9 @@
// "USERPREFS_OEM_IMAGE_WIDTH": "50",
// "USERPREFS_OEM_IMAGE_HEIGHT": "28",
// "USERPREFS_OEM_IMAGE_DATA": "{ 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00, 0x18, 0x1F, 0xF0, 0x67, 0x00, 0x00, 0x00, 0x30, 0x1F, 0xF8, 0x33, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFC, 0x31, 0x00, 0x00, 0x00, 0x60, 0x00, 0xFE, 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x7E, 0x18, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x3F, 0x0C, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x81, 0x1F, 0x06, 0x00, 0x00, 0x00, 0x80, 0xC1, 0x0F, 0x06, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xC7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00}",
// "USERPREFS_NETWORK_ENABLED_PROTOCOLS": "1", // Enable UDP mesh
// "USERPREFS_NETWORK_WIFI_ENABLED": "true",
// "USERPREFS_NETWORK_WIFI_SSID": "wifi_ssid",
// "USERPREFS_NETWORK_WIFI_PSK": "wifi_psk",
"USERPREFS_TZ_STRING": "tzplaceholder "
}

Wyświetl plik

@ -1,8 +1,7 @@
[env:CDEBYTE_E77-MBL]
extends = stm32_base
; `ebyte_e77_dev` was added in this commit. Remove when a new release is used in the base.
platform = https://github.com/platformio/platform-ststm32.git#3208828db447f4373cd303b7f7393c8fc0dae623
board = ebyte_e77_dev
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
board_level = extra
build_flags =
${stm32_base.build_flags}
@ -11,31 +10,19 @@ build_flags =
-DPIN_SERIAL_RX=PA3
-DPIN_SERIAL_TX=PA2
-DHAL_DAC_MODULE_ONLY
-DHAL_ADC_MODULE_DISABLED
-DHAL_COMP_MODULE_DISABLED
-DHAL_CRC_MODULE_DISABLED
-DHAL_CRYP_MODULE_DISABLED
-DHAL_GTZC_MODULE_DISABLED
-DHAL_HSEM_MODULE_DISABLED
-DHAL_I2C_MODULE_DISABLED
-DHAL_I2S_MODULE_DISABLED
-DHAL_IPCC_MODULE_DISABLED
-DHAL_IRDA_MODULE_DISABLED
-DHAL_IWDG_MODULE_DISABLED
-DHAL_LPTIM_MODULE_DISABLED
-DHAL_PKA_MODULE_DISABLED
-DHAL_RNG_MODULE_DISABLED
-DHAL_RTC_MODULE_DISABLED
-DHAL_SMARTCARD_MODULE_DISABLED
-DHAL_SMBUS_MODULE_DISABLED
-DHAL_TIM_MODULE_DISABLED
-DHAL_WWDG_MODULE_DISABLED
-DHAL_EXTI_MODULE_DISABLED
-DHAL_SAI_MODULE_DISABLED
-DHAL_ICACHE_MODULE_DISABLED
-DHAL_RNG_MODULE_ENABLED
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_LR11X0=1
; -D PIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
-DMESHTASTIC_EXCLUDE_I2C=1
-DMESHTASTIC_EXCLUDE_WIFI=1
-DMESHTASTIC_EXCLUDE_BLUETOOTH=1
-DMESHTASTIC_EXCLUDE_GPS=1
-DMESHTASTIC_EXCLUDE_SCREEN=1
-DMESHTASTIC_EXCLUDE_MQTT=1
-DMESHTASTIC_EXCLUDE_POWERMON=1
;-DPIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
;-DCFG_DEBUG
upload_port = stlink

Wyświetl plik

@ -0,0 +1,29 @@
; First prototype eink/nrf52840/sx1262 device
[env:thinknode_m1]
extends = nrf52840_base
board = ThinkNode-M1
board_check = true
debug_tool = jlink
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
build_flags = ${nrf52840_base.build_flags} -Ivariants/ELECROW-ThinkNode-M1
-DELECROW_ThinkNode_M1
-DGPS_POWER_TOGGLE
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DEINK_DISPLAY_MODEL=GxEPD2_154_D67
-DEINK_WIDTH=200
-DEINK_HEIGHT=200
-DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-DEINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted //20
-DEINK_LIMIT_RATE_BACKGROUND_SEC=10 ; Minimum interval between BACKGROUND updates //30
-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates
; -DEINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/ELECROW-ThinkNode-M1>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
lewisxhe/PCF8563_Library@^1.0.1
khoih-prog/nRF52_PWM@^1.0.1
;upload_protocol = fs

Wyświetl plik

@ -0,0 +1,44 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
void initVariant()
{
// LED1 & LED2
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
pinMode(PIN_LED2, OUTPUT);
ledOff(PIN_LED2);
pinMode(PIN_LED3, OUTPUT);
ledOff(PIN_LED3);
}

Wyświetl plik

@ -0,0 +1,205 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_ELECROW_EINK_V1_0_
#define _VARIANT_ELECROW_EINK_V1_0_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
// 在PinDescription数组中定义的引脚数
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (1)
#define NUM_ANALOG_OUTPUTS (0)
#define PIN_LED1 -1
#define PIN_LED2 -1
#define PIN_LED3 -1
// LED
#define POWER_LED (32 + 6) // red
#define LED_POWER (32 + 4)
#define USER_LED (0 + 13) // green
// USB_CHECK
#define USB_CHECK (32 + 3)
#define ADC_V (0 + 8)
#define LED_RED PIN_LED3
#define LED_BLUE PIN_LED1
#define LED_GREEN PIN_LED2
#define LED_BUILTIN LED_BLUE
#define LED_CONN PIN_GREEN
#define LED_STATE_ON 0 // State when LED is lit // LED灯亮时的状态
#define M1_buzzer (0 + 6)
/*
* Buttons
*/
#define PIN_BUTTON2 (32 + 10)
#define PIN_BUTTON1 (32 + 7)
// #define PIN_BUTTON1 (0 + 11)
// #define PIN_BUTTON1 (32 + 7)
// #define BUTTON_CLICK_MS 400
// #define BUTTON_TOUCH_MS 200
/*
* Analog pins
*/
#define PIN_A0 (4) // Battery ADC
#define BATTERY_PIN PIN_A0
static const uint8_t A0 = PIN_A0;
#define ADC_RESOLUTION 14
#define PIN_NFC1 (9)
#define PIN_NFC2 (10)
/*Wire Interfaces*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (26)
#define PIN_WIRE_SCL (27)
/* touch sensor, active high */
#define TP_SER_IO (0 + 11)
#define PIN_RTC_INT (0 + 16) // Interrupt from the PCF8563 RTC
/*
External serial flash WP25R1635FZUIL0
*/
// QSPI Pins
#define PIN_QSPI_SCK (32 + 14)
#define PIN_QSPI_CS (32 + 15)
#define PIN_QSPI_IO0 (32 + 12) // MOSI if using two bit interface
#define PIN_QSPI_IO1 (32 + 13) // MISO if using two bit interface
#define PIN_QSPI_IO2 (0 + 7) // WP if using two bit interface (i.e. not used)
#define PIN_QSPI_IO3 (0 + 5) // HOLD if using two bit interface (i.e. not used)
// On-board QSPI Flash
#define EXTERNAL_FLASH_DEVICES MX25R1635F
#define EXTERNAL_FLASH_USE_QSPI
/*
* Lora radio
*/
#define SX126X_POWER_EN (0 + 21)
#define USE_SX1262
#define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (0 + 20)
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
// #define SX1262_DIO3 (0 + 21) // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not
// drive from the main
#define SX126X_BUSY (0 + 17)
#define SX126X_RESET (0 + 25)
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 3.3
#define PIN_EINK_EN (32 + 11) // Note: this is really just backlight power
#define PIN_EINK_CS (0 + 30)
#define PIN_EINK_BUSY (0 + 3)
#define PIN_EINK_DC (0 + 28)
#define PIN_EINK_RES (0 + 2)
#define PIN_EINK_SCLK (0 + 31)
#define PIN_EINK_MOSI (0 + 29) // also called SDI
// Controls power for all peripherals (eink + GPS + LoRa + Sensor)
#define PIN_POWER_EN (0 + 12)
#define USE_EINK
#define PIN_SPI1_MISO (32 + 7)
#define PIN_SPI1_MOSI PIN_EINK_MOSI
#define PIN_SPI1_SCK PIN_EINK_SCLK
/*
* GPS pins
*/
// #define HAS_GPS 1
#define GPS_L76K
#define GPS_BAUDRATE 9600
#define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
// Seems to be missing on this new board
// #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
#define GPS_TX_PIN (32 + 9) // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN (32 + 8) // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50
#define PIN_GPS_PPS (32 + 1) // GPS开关判断
#define PIN_SERIAL1_RX GPS_TX_PIN
#define PIN_SERIAL1_TX GPS_RX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 2
// For LORA, spi 0
#define PIN_SPI_MISO (0 + 23)
#define PIN_SPI_MOSI (0 + 22)
#define PIN_SPI_SCK (0 + 19)
#define PIN_PWR_EN (0 + 6)
// To debug via the segger JLINK console rather than the CDC-ACM serial device
// #define USE_SEGGER
// Battery
// The battery sense is hooked to pin A0 (4)
// it is defined in the anlaolgue pin section of this file
// and has 12 bit resolution
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (2.02F)
// #define HAS_RTC 0
// #define HAS_SCREEN 0
#ifdef __cplusplus
}
#endif
#endif

Wyświetl plik

@ -0,0 +1,28 @@
// Need this file for ESP32-S3
// No need to modify this file, changes to pins imported from variant.h
// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#include <variant.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
// Serial
static const uint8_t TX = UART_TX;
static const uint8_t RX = UART_RX;
// Default SPI will be mapped to Radio
static const uint8_t SS = LORA_CS;
static const uint8_t SCK = LORA_SCK;
static const uint8_t MOSI = LORA_MOSI;
static const uint8_t MISO = LORA_MISO;
// The default Wire will be mapped to PMU and RTC
static const uint8_t SCL = I2C_SCL;
static const uint8_t SDA = I2C_SDA;
#endif /* Pins_Arduino_h */

Wyświetl plik

@ -0,0 +1,7 @@
[env:thinknode_m2]
extends = esp32s3_base
board = ESP32-S3-WROOM-1-N4
build_flags =
${esp32s3_base.build_flags}
-D ELECROW_ThinkNode_M2
-I variants/ELECROW-ThinkNode-M2

Wyświetl plik

@ -0,0 +1,64 @@
// Status
#define LED_PIN_POWER 1
#define BIAS_T_ENABLE LED_PIN_POWER
#define BIAS_T_VALUE HIGH
#define PIN_BUTTON1 47 // 功能键
#define PIN_BUTTON2 4 // 电源键
#define POWER_CFG
#define POWER_CHRG 6
#define POWER_FULL 42
#define PIN_BUZZER 5
#define I2C_SCL 15
#define I2C_SDA 16
#define UART_TX 43
#define UART_RX 44
#define VEXT_ENABLE 46 // for OLED
#define VEXT_ON_VALUE HIGH
#define SX126X_CS 10
#define LORA_SCK 12
#define LORA_MOSI 11
#define LORA_MISO 13
#define SX126X_RESET 21
#define SX126X_BUSY 14
#define SX126X_DIO1 3
#define SX126X_DIO2_AS_RF_SWITCH
// #define SX126X_DIO3 9
#define SX126X_DIO3_TCXO_VOLTAGE 3.3
#define SX126X_MAX_POWER 22 // SX126xInterface.cpp defaults to 22 if not defined, but here we define it for good practice
#define USE_SX1262
#define LORA_CS SX126X_CS // FIXME: for some reason both are used in /src
#define LORA_DIO1 SX126X_DIO1
#define SX126X_POWER_EN 48
// Battery
// #define BATTERY_PIN 2
#define BATTERY_PIN 17
// #define ADC_CHANNEL ADC1_GPIO2_CHANNEL
#define ADC_CHANNEL ADC2_GPIO17_CHANNEL
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (1.548F)
#define BAT_MEASURE_ADC_UNIT 2
#define HAS_SCREEN 1
#define USE_SH1106 1
// PCF8563 RTC Module
// #define PCF8563_RTC 0x51
// #define PIN_RTC_INT 48 // Interrupt from the PCF8563 RTC
#define HAS_RTC 0
#define HAS_GPS 0
#define BUTTON_PIN PIN_BUTTON1
#define BUTTON_PIN_ALT PIN_BUTTON2

Wyświetl plik

@ -11,7 +11,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_eink -
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_eink>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
zinggjm/GxEPD2@^1.6.2
debug_tool = jlink
;upload_port = /dev/ttyACM4

Wyświetl plik

@ -7,5 +7,5 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_oled -
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_oled>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
debug_tool = jlink

Wyświetl plik

@ -24,7 +24,7 @@ build_flags =
;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
[env:crowpanel-esp32s3-4-epaper]
extends = esp32s3_base
@ -39,7 +39,7 @@ board = esp32-s3-devkitc-1
board_level = extra
upload_protocol = esptool
build_flags =
${esp32_base.build_flags} -D CROWPANEL_ESP32S3_5_EPAPER -I variants/crowpanel-esp32s3-5-epaper
${esp32_base.build_flags} -D CROWPANEL_ESP32S3_4_EPAPER -I variants/crowpanel-esp32s3-5-epaper
-D PRIVATE_HW
-DBOARD_HAS_PSRAM
-DGPS_POWER_TOGGLE
@ -52,7 +52,7 @@ build_flags =
;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
[env:crowpanel-esp32s3-2-epaper]
extends = esp32s3_base
@ -67,7 +67,7 @@ board = esp32-s3-devkitc-1
board_level = extra
upload_protocol = esptool
build_flags =
${esp32_base.build_flags} -D CROWPANEL_ESP32S3_5_EPAPER -I variants/crowpanel-esp32s3-5-epaper
${esp32_base.build_flags} -D CROWPANEL_ESP32S3_2_EPAPER -I variants/crowpanel-esp32s3-5-epaper
-D PRIVATE_HW
-DBOARD_HAS_PSRAM
-DGPS_POWER_TOGGLE
@ -80,4 +80,4 @@ build_flags =
;-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip

Wyświetl plik

@ -0,0 +1,12 @@
[env:hackerboxes-esp32-io]
extends = esp32_base
board = esp32dev
board_level = extra
build_flags =
${esp32_base.build_flags}
-D PRIVATE_HW
-I variants/hackerboxes_esp32_io
monitor_speed = 115200
upload_protocol = esptool
;upload_port = /dev/ttyUSB0
upload_speed = 921600

Wyświetl plik

@ -0,0 +1,30 @@
#define BUTTON_PIN 0
// HACKBOX LoRa IO Kit
// Uses a ESP-32-WROOM and a RA-01SH (SX1262) LoRa Board
#define LED_PIN 2 // LED
#define LED_STATE_ON 1 // State when LED is lit
#define HAS_SCREEN 0
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define USE_SX1262
#define LORA_SCK 18
#define LORA_MISO 19
#define LORA_MOSI 23
#define LORA_CS 5
#define LORA_DIO0 RADIOLIB_NC
#define LORA_RESET 27
#define LORA_DIO1 33
#define LORA_DIO2 RADIOLIB_NC
#define LORA_BUSY 32
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_BUSY
#define SX126X_RESET LORA_RESET
#define SX126X_MAX_POWER 22 // Max power of the RA-01SH is 22db

Wyświetl plik

@ -0,0 +1,14 @@
[env:hackerboxes-esp32c3-oled]
extends = esp32c3_base
board = esp32-c3-devkitm-1
board_level = extra
build_flags =
${esp32_base.build_flags}
-D PRIVATE_HW
-D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1
-I variants/hackerboxes_esp32c3_oled
monitor_speed = 115200
upload_protocol = esptool
;upload_port = /dev/ttyUSB0
upload_speed = 921600

Wyświetl plik

@ -0,0 +1,36 @@
#define BUTTON_PIN 9
// Hackerboxes LoRa ESP32-C3 OLED Kit
// Uses a ESP32-C3 OLED Board and a RA-01SH (SX1262) LoRa Board
#define LED_PIN 8 // LED
#define LED_STATE_ON 1 // State when LED is lit
#define HAS_SCREEN 0
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
// #define USE_SSD1306_72_40
// #define I2C_SDA 5 // I2C pins for this board
// #define I2C_SCL 6 //
// #define TFT_WIDTH 72
// #define TFT_HEIGHT 40
#define USE_SX1262
#define LORA_SCK 4
#define LORA_MISO 7
#define LORA_MOSI 3
#define LORA_CS 1
#define LORA_DIO0 RADIOLIB_NC
#define LORA_RESET 0
#define LORA_DIO1 20
#define LORA_DIO2 RADIOLIB_NC
#define LORA_BUSY 10
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_BUSY
#define SX126X_RESET LORA_RESET
#define SX126X_MAX_POWER 22 // Max power of the RA-01SH is 22db

Wyświetl plik

@ -14,4 +14,4 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_node
lib_deps =
${nrf52840_base.lib_deps}
lewisxhe/PCF8563_Library@^1.0.1
https://github.com/meshtastic/st7789#bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f
https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip

Wyświetl plik

@ -0,0 +1,11 @@
[env:heltec_sensor_hub]
extends = esp32s3_base
board = heltec_wifi_lora_32_V3
board_check = true
build_flags =
${esp32s3_base.build_flags} -I variants/heltec_sensor_hub
-D HELTEC_SENSOR_HUB
lib_deps = ${esp32s3_base.lib_deps}
adafruit/Adafruit NeoPixel @ ^1.12.0

Wyświetl plik

@ -0,0 +1,46 @@
#define EXT_PWR_DETECT 20
#define BUTTON_PIN 17
#define BATTERY_PIN 7 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO7_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
#define ADC_MULTIPLIER (4.9 * 1.045)
#define ADC_CTRL 34 // active HIGH, powers the voltage divider. Only on 1.1
#define ADC_CTRL_ENABLED HIGH
#define HAS_NEOPIXEL // Enable the use of neopixels
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
#define NEOPIXEL_DATA 18 // gpio pin used to send data to the neopixels
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use
#define USE_SX1262
#define LORA_DIO0 RADIOLIB_NC
#define LORA_RESET 12
#define LORA_DIO1 14 // SX1262 IRQ
#define LORA_DIO2 13 // SX1262 BUSY
#define LORA_SCK 9
#define LORA_MISO 11
#define LORA_MOSI 10
#define LORA_CS 8
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define I2C_SDA 1
#define I2C_SCL 2
#define HAS_SCREEN 0
#define SENSOR_POWER_CTRL_PIN 33
#define SENSOR_POWER_ON 1
#define PERIPHERAL_WARMUP_MS 100
#define ESP32S3_WAKE_TYPE ESP_EXT1_WAKEUP_ANY_HIGH
#define ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE 1

Wyświetl plik

@ -16,7 +16,7 @@ build_flags =
-DEINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting"
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2#b202ebfec6a4821e098cf7a625ba0f6f2400292d
https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip
lewisxhe/PCF8563_Library@^1.0.1
upload_speed = 115200

Wyświetl plik

@ -20,7 +20,7 @@ build_flags =
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2#448c8538129fde3d02a7cb5e6fc81971ad92547f
https://github.com/meshtastic/GxEPD2/archive/448c8538129fde3d02a7cb5e6fc81971ad92547f.zip
lewisxhe/PCF8563_Library@^1.0.1
upload_speed = 115200

Wyświetl plik

@ -9,5 +9,5 @@ build_flags =
lib_deps =
${esp32s3_base.lib_deps}
lewisxhe/PCF8563_Library@^1.0.1
https://github.com/meshtastic/st7789#bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f
https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip
upload_speed = 921600

Wyświetl plik

@ -17,7 +17,7 @@ build_flags =
-D EINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting"
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2#b202ebfec6a4821e098cf7a625ba0f6f2400292d
https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip
lewisxhe/PCF8563_Library@^1.0.1
upload_speed = 115200

Wyświetl plik

@ -15,6 +15,6 @@ build_flags =
-D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a
https://github.com/meshtastic/GxEPD2/archive/55f618961db45a23eff0233546430f1e5a80f63a.zip
lewisxhe/PCF8563_Library@^1.0.1
upload_speed = 115200

Wyświetl plik

@ -23,7 +23,7 @@ build_flags = ${nrf52840_base.build_flags} -I variants/meshlink -D MESHLINK
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/meshlink>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a
https://github.com/meshtastic/GxEPD2/archive/55f618961db45a23eff0233546430f1e5a80f63a.zip
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds

Wyświetl plik

@ -23,7 +23,7 @@ build_flags = ${nrf52840_base.build_flags} -I variants/meshlink_eink -D MESHLINK
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/meshlink_eink>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a
https://github.com/meshtastic/GxEPD2/archive/55f618961db45a23eff0233546430f1e5a80f63a.zip
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds

Wyświetl plik

@ -9,7 +9,7 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/monteops_hw1> +<
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}
https://github.com/RAKWireless/RAK13800-W5100S.git#1.0.2
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
;upload_protocol = jlink

Wyświetl plik

@ -27,6 +27,7 @@ build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunctio
-D USE_X11=1
-D HAS_TFT=1
-D HAS_SCREEN=0
-D LV_CACHE_DEF_SIZE=6291456
-D LV_BUILD_TEST=0
-D LV_USE_LIBINPUT=1
-D LV_LVGL_H_INCLUDE_SIMPLE
@ -56,7 +57,7 @@ build_flags = ${native_base.build_flags} -O0 -fsanitize=address -lX11 -linput -l
-D USE_X11=1
-D HAS_TFT=1
-D HAS_SCREEN=0
; -D CALIBRATE_TOUCH=0
-D LV_CACHE_DEF_SIZE=6291456
-D LV_BUILD_TEST=0
-D LV_USE_LOG=1
-D LV_USE_SYSMON=1

Wyświetl plik

@ -13,4 +13,4 @@ board_build.f_cpu = 240000000L
upload_protocol = esptool
lib_deps =
${esp32_base.lib_deps}
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
https://github.com/gjelsoe/STK8xxx-Accelerometer/archive/v0.1.1.zip

Wyświetl plik

@ -15,6 +15,6 @@ lib_deps =
${rp2040_base.lib_deps}
${networking_base.lib_deps}
melopero/Melopero RV3028@^1.1.0
https://github.com/RAKWireless/RAK13800-W5100S.git#1.0.2
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
debug_build_flags = ${rp2040_base.build_flags}, -g
debug_tool = cmsis-dap ; for e.g. Picotool

Wyświetl plik

@ -15,7 +15,7 @@ lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}
melopero/Melopero RV3028@^1.1.0
https://github.com/beegee-tokyo/RAK-OneWireSerial.git#0.0.2
https://github.com/beegee-tokyo/RAK-OneWireSerial/archive/0.0.2.zip
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
;upload_protocol = jlink

Wyświetl plik

@ -1,36 +1,23 @@
[env:rak3172]
extends = stm32_base
board = wiscore_rak3172
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
build_flags =
${stm32_base.build_flags}
-Ivariants/rak3172
-DSERIAL_UART_INSTANCE=1
-DPIN_SERIAL_RX=PB7
-DPIN_SERIAL_TX=PB6
-DHAL_DAC_MODULE_ONLY
-DHAL_ADC_MODULE_DISABLED
-DHAL_COMP_MODULE_DISABLED
-DHAL_CRC_MODULE_DISABLED
-DHAL_CRYP_MODULE_DISABLED
-DHAL_GTZC_MODULE_DISABLED
-DHAL_HSEM_MODULE_DISABLED
-DHAL_I2C_MODULE_DISABLED
-DHAL_I2S_MODULE_DISABLED
-DHAL_IPCC_MODULE_DISABLED
-DHAL_IRDA_MODULE_DISABLED
-DHAL_IWDG_MODULE_DISABLED
-DHAL_LPTIM_MODULE_DISABLED
-DHAL_PKA_MODULE_DISABLED
-DHAL_RNG_MODULE_DISABLED
-DHAL_RTC_MODULE_DISABLED
-DHAL_SMARTCARD_MODULE_DISABLED
-DHAL_SMBUS_MODULE_DISABLED
-DHAL_TIM_MODULE_DISABLED
-DHAL_WWDG_MODULE_DISABLED
-DHAL_EXTI_MODULE_DISABLED
-DHAL_SAI_MODULE_DISABLED
-DHAL_ICACHE_MODULE_DISABLED
-DHAL_RNG_MODULE_ENABLED
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_LR11X0=1
upload_port = stlink
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
-DMESHTASTIC_EXCLUDE_I2C=1
-DMESHTASTIC_EXCLUDE_WIFI=1
-DMESHTASTIC_EXCLUDE_BLUETOOTH=1
-DMESHTASTIC_EXCLUDE_GPS=1
-DMESHTASTIC_EXCLUDE_SCREEN=1
-DMESHTASTIC_EXCLUDE_MQTT=1
-DMESHTASTIC_EXCLUDE_POWERMON=1
;-DPIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
;-DCFG_DEBUG
upload_port = stlink

Wyświetl plik

@ -1,3 +1,8 @@
/*
STM32WLE5 Core Module for LoRaWAN® RAK3372
https://store.rakwireless.com/products/wisblock-core-module-rak3372
*/
/*
This variant is a work in progress.
Do not expect a working Meshtastic device with this target.
@ -8,4 +13,7 @@ Do not expect a working Meshtastic device with this target.
#define USE_STM32WLx
#endif
#define LED_PIN PA0 // Green LED
#define LED_STATE_ON 1
#endif

Some files were not shown because too many files have changed in this diff Show More