mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-10 11:57:25 +00:00
Compare commits
25 Commits
v2.6.2.31c
...
v2.6.3.640
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
640e731ad2 | ||
|
|
ba81a8ad87 | ||
|
|
83d8e3cb09 | ||
|
|
6429eca5e4 | ||
|
|
13101c1bab | ||
|
|
d28af68b5a | ||
|
|
53a7afff41 | ||
|
|
eb375d8e62 | ||
|
|
33f2b7144f | ||
|
|
e5f8218d34 | ||
|
|
0ddb507055 | ||
|
|
3afe84c4f4 | ||
|
|
e9d8a3d7f9 | ||
|
|
e722a97987 | ||
|
|
daa4186d65 | ||
|
|
1ee800e901 | ||
|
|
cf7f0f9d08 | ||
|
|
1e4a0134e6 | ||
|
|
0951fdd49b | ||
|
|
848a3ed6a1 | ||
|
|
fd7a1f2ccb | ||
|
|
5acaf8f897 | ||
|
|
cff93adb5e | ||
|
|
e4d3ec1f59 | ||
|
|
ae27aaaf43 |
9
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
9
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -72,6 +72,15 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
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
|
- type: input
|
||||||
id: version
|
id: version
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ plugins:
|
|||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- prettier@3.5.3
|
- prettier@3.5.3
|
||||||
- trufflehog@3.88.17
|
- trufflehog@3.88.18
|
||||||
- yamllint@1.36.2
|
- yamllint@1.37.0
|
||||||
- bandit@1.8.3
|
- bandit@1.8.3
|
||||||
- checkov@3.2.386
|
- checkov@3.2.392
|
||||||
- terrascan@1.19.9
|
- terrascan@1.19.9
|
||||||
- trivy@0.60.0
|
- trivy@0.60.0
|
||||||
- taplo@0.9.3
|
- taplo@0.9.3
|
||||||
- ruff@0.11.0
|
- ruff@0.11.2
|
||||||
- isort@6.0.1
|
- isort@6.0.1
|
||||||
- markdownlint@0.44.0
|
- markdownlint@0.44.0
|
||||||
- oxipng@9.1.4
|
- oxipng@9.1.4
|
||||||
@@ -28,7 +28,7 @@ lint:
|
|||||||
- shellcheck@0.10.0
|
- shellcheck@0.10.0
|
||||||
- black@25.1.0
|
- black@25.1.0
|
||||||
- git-diff-check
|
- git-diff-check
|
||||||
- gitleaks@8.24.0
|
- gitleaks@8.24.2
|
||||||
- clang-format@16.0.3
|
- clang-format@16.0.3
|
||||||
ignore:
|
ignore:
|
||||||
- linters: [ALL]
|
- linters: [ALL]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
|
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
|
||||||
[portduino_base]
|
[portduino_base]
|
||||||
platform = https://github.com/meshtastic/platform-native.git#df71ed0040e9aad767a002829330965b78fc452a
|
platform = https://github.com/meshtastic/platform-native.git#e82ba1a19b6cd1dc55cbde29b33ea8dd0640014f
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
[stm32_base]
|
[stm32_base]
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
platform = platformio/ststm32
|
platform = ststm32
|
||||||
platform_packages = platformio/framework-arduinoststm32@^4.20900.0
|
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32.git#2.9.0
|
||||||
|
extra_scripts =
|
||||||
|
${env.extra_scripts}
|
||||||
|
post:extra_scripts/extra_stm32.py
|
||||||
|
|
||||||
build_type = release
|
build_type = release
|
||||||
|
|
||||||
;board_build.flash_offset = 0x08000000
|
build_flags =
|
||||||
|
|
||||||
build_flags =
|
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
-flto
|
-flto
|
||||||
-Isrc/platform/stm32wl -g
|
-Isrc/platform/stm32wl -g
|
||||||
@@ -18,27 +19,24 @@ build_flags =
|
|||||||
-DMESHTASTIC_EXCLUDE_SCREEN
|
-DMESHTASTIC_EXCLUDE_SCREEN
|
||||||
-DMESHTASTIC_EXCLUDE_MQTT
|
-DMESHTASTIC_EXCLUDE_MQTT
|
||||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
-DMESHTASTIC_EXCLUDE_PKI
|
|
||||||
-DMESHTASTIC_EXCLUDE_GPS
|
-DMESHTASTIC_EXCLUDE_GPS
|
||||||
; -DVECT_TAB_OFFSET=0x08000000
|
;-DDEBUG_MUTE
|
||||||
-DconfigUSE_CMSIS_RTOS_V2=1
|
|
||||||
; -DSPI_MODE_0=SPI_MODE0
|
|
||||||
-fmerge-all-constants
|
-fmerge-all-constants
|
||||||
-ffunction-sections
|
-ffunction-sections
|
||||||
-fdata-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>
|
${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
|
board_upload.offset_address = 0x08000000
|
||||||
upload_protocol = stlink
|
upload_protocol = stlink
|
||||||
|
debug_tool = stlink
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
charlesbaynham/OSFS@^1.2.3
|
${radiolib_base.lib_deps}
|
||||||
jgromes/RadioLib@7.0.2
|
https://github.com/caveman99/Crypto.git#eae9c768054118a9399690f8af202853d1ae8516
|
||||||
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
|
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
mathertel/OneButton@2.6.1
|
mathertel/OneButton@2.6.1
|
||||||
Wire
|
Wire
|
||||||
|
|||||||
22
extra_scripts/extra_stm32.py
Executable file
22
extra_scripts/extra_stm32.py
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
# trunk-ignore-all(ruff/F821)
|
||||||
|
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
# Custom HEX from ELF
|
||||||
|
env.AddPostAction(
|
||||||
|
"$BUILD_DIR/${PROGNAME}.elf",
|
||||||
|
env.VerboseAction(
|
||||||
|
" ".join(
|
||||||
|
[
|
||||||
|
"$OBJCOPY",
|
||||||
|
"-O",
|
||||||
|
"ihex",
|
||||||
|
"-R",
|
||||||
|
".eeprom",
|
||||||
|
"$BUILD_DIR/${PROGNAME}.elf",
|
||||||
|
"$BUILD_DIR/${PROGNAME}.hex",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
"Building $BUILD_DIR/${PROGNAME}.hex",
|
||||||
|
),
|
||||||
|
)
|
||||||
@@ -94,7 +94,7 @@ lib_deps =
|
|||||||
|
|
||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/meshtastic/device-ui.git#74e739ed4532ca10393df9fc89ae5a22f0bab2b1
|
https://github.com/meshtastic/device-ui.git#7a6ffba3c86901b0e3234b6c056aa803b4cd8854
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
; (not included in native / portduino)
|
; (not included in native / portduino)
|
||||||
|
|||||||
Submodule protobufs updated: 14ec205865...b4044f8f9f
@@ -41,10 +41,8 @@ class AudioThread : public concurrency::OSThread
|
|||||||
delete i2sRtttl;
|
delete i2sRtttl;
|
||||||
i2sRtttl = nullptr;
|
i2sRtttl = nullptr;
|
||||||
}
|
}
|
||||||
if (rtttlFile != nullptr) {
|
delete rtttlFile;
|
||||||
delete rtttlFile;
|
rtttlFile = nullptr;
|
||||||
rtttlFile = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
setCPUFast(false);
|
setCPUFast(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
|||||||
#ifdef USERPREFS_BUTTON_PIN
|
#ifdef USERPREFS_BUTTON_PIN
|
||||||
int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
|
int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
|
||||||
#endif
|
#endif
|
||||||
#if defined(HELTEC_CAPSULE_SENSOR_V3)
|
#if defined(HELTEC_CAPSULE_SENSOR_V3) || defined(HELTEC_SENSOR_HUB)
|
||||||
this->userButton = OneButton(pin, false, false);
|
this->userButton = OneButton(pin, false, false);
|
||||||
#elif defined(BUTTON_ACTIVE_LOW)
|
#elif defined(BUTTON_ACTIVE_LOW)
|
||||||
this->userButton = OneButton(pin, BUTTON_ACTIVE_LOW, BUTTON_ACTIVE_PULLUP);
|
this->userButton = OneButton(pin, BUTTON_ACTIVE_LOW, BUTTON_ACTIVE_PULLUP);
|
||||||
|
|||||||
@@ -29,30 +29,6 @@ SPIClass SPI1(HSPI);
|
|||||||
|
|
||||||
#endif // HAS_SDCARD
|
#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.
|
* @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)
|
bool copyFile(const char *from, const char *to)
|
||||||
{
|
{
|
||||||
#ifdef ARCH_STM32WL
|
#ifdef FSCom
|
||||||
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)
|
|
||||||
// take SPI Lock
|
// take SPI Lock
|
||||||
concurrency::LockGuard g(spiLock);
|
concurrency::LockGuard g(spiLock);
|
||||||
unsigned char cbuffer[16];
|
unsigned char cbuffer[16];
|
||||||
@@ -127,13 +77,7 @@ bool copyFile(const char *from, const char *to)
|
|||||||
*/
|
*/
|
||||||
bool renameFile(const char *pathFrom, const char *pathTo)
|
bool renameFile(const char *pathFrom, const char *pathTo)
|
||||||
{
|
{
|
||||||
#ifdef ARCH_STM32WL
|
#ifdef FSCom
|
||||||
if (copyFile(pathFrom, pathTo) && (OSFS::deleteFile(pathFrom) == OSFS::result::NO_ERROR)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#elif defined(FSCom)
|
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// take SPI Lock
|
// take SPI Lock
|
||||||
|
|||||||
@@ -15,13 +15,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_STM32WL)
|
#if defined(ARCH_STM32WL)
|
||||||
// STM32WL series 2 Kbytes (8 rows of 256 bytes)
|
// STM32WL
|
||||||
#include <EEPROM.h>
|
#include "LittleFS.h"
|
||||||
#include <OSFS.h>
|
#define FSCom InternalFS
|
||||||
|
#define FSBegin() FSCom.begin()
|
||||||
// Useful consts
|
using namespace STM32_LittleFS_Namespace;
|
||||||
const OSFS::result noerr = OSFS::result::NO_ERROR;
|
|
||||||
const OSFS::result notfound = OSFS::result::FILE_NOT_FOUND;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_RP2040)
|
#if defined(ARCH_RP2040)
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
virtual bool isVbusIn() override
|
virtual bool isVbusIn() override
|
||||||
{
|
{
|
||||||
#ifdef EXT_PWR_DETECT
|
#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 external powered that pin will be pulled down
|
||||||
if (digitalRead(EXT_PWR_DETECT) == LOW) {
|
if (digitalRead(EXT_PWR_DETECT) == LOW) {
|
||||||
return true;
|
return true;
|
||||||
@@ -541,7 +541,7 @@ Power::Power() : OSThread("Power")
|
|||||||
bool Power::analogInit()
|
bool Power::analogInit()
|
||||||
{
|
{
|
||||||
#ifdef EXT_PWR_DETECT
|
#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);
|
pinMode(EXT_PWR_DETECT, INPUT_PULLUP);
|
||||||
#else
|
#else
|
||||||
pinMode(EXT_PWR_DETECT, INPUT);
|
pinMode(EXT_PWR_DETECT, INPUT);
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MLX90614_ADDR_DEF 0x5A
|
#define MLX90614_ADDR_DEF 0x5A
|
||||||
#define CGRADSENS_ADDR 0x66
|
#define CGRADSENS_ADDR 0x66
|
||||||
#define LTR390UV_ADDR 0x53
|
#define LTR390UV_ADDR 0x53
|
||||||
|
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// ACCELEROMETER
|
// ACCELEROMETER
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
|||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||||
{
|
{
|
||||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB};
|
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB, TCA8418KB};
|
||||||
return firstOfOrNONE(5, types);
|
return firstOfOrNONE(6, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||||
@@ -74,4 +74,4 @@ bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) cons
|
|||||||
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address));
|
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address));
|
||||||
}
|
}
|
||||||
|
|
||||||
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
|
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class ScanI2C
|
|||||||
TDECKKB,
|
TDECKKB,
|
||||||
BBQ10KB,
|
BBQ10KB,
|
||||||
RAK14004,
|
RAK14004,
|
||||||
PMU_AXP192_AXP2101,
|
PMU_AXP192_AXP2101, // has the same address as the TCA8418KB
|
||||||
BME_680,
|
BME_680,
|
||||||
BME_280,
|
BME_280,
|
||||||
BMP_280,
|
BMP_280,
|
||||||
@@ -69,6 +69,7 @@ class ScanI2C
|
|||||||
DFROBOT_RAIN,
|
DFROBOT_RAIN,
|
||||||
DPS310,
|
DPS310,
|
||||||
LTR390UV,
|
LTR390UV,
|
||||||
|
TCA8418KB,
|
||||||
} DeviceType;
|
} DeviceType;
|
||||||
|
|
||||||
// typedef uint8_t DeviceAddress;
|
// typedef uint8_t DeviceAddress;
|
||||||
@@ -132,4 +133,4 @@ class ScanI2C
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool shouldSuppressScreen = false;
|
bool shouldSuppressScreen = false;
|
||||||
};
|
};
|
||||||
@@ -10,11 +10,6 @@
|
|||||||
#include "meshUtils.h" // vformat
|
#include "meshUtils.h" // vformat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
|
||||||
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
|
||||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool in_array(uint8_t *array, int size, uint8_t lookfor)
|
bool in_array(uint8_t *array, int size, uint8_t lookfor)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -211,6 +206,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case XPOWERS_AXP192_AXP2101_ADDRESS:
|
||||||
|
// Do we have the TCA8418 instead?
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x02), 1);
|
||||||
|
if ((registerValue & 0b11100000) == 0) {
|
||||||
|
logFoundDevice("TCA8418", (uint8_t)addr.address);
|
||||||
|
type = TCA8418KB;
|
||||||
|
} else {
|
||||||
|
logFoundDevice("AXP192/AXP2101", (uint8_t)addr.address);
|
||||||
|
type = PMU_AXP192_AXP2101;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
||||||
|
|
||||||
@@ -218,9 +225,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_PMU
|
|
||||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address)
|
|
||||||
#endif
|
|
||||||
case BME_ADDR:
|
case BME_ADDR:
|
||||||
case BME_ADDR_ALTERNATE:
|
case BME_ADDR_ALTERNATE:
|
||||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
|
||||||
@@ -536,4 +541,4 @@ void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
|
|||||||
{
|
{
|
||||||
LOG_INFO("%s found at address 0x%x", device, address);
|
LOG_INFO("%s found at address 0x%x", device, address);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1200,12 +1200,12 @@ GnssModel_t GPS::probe(int serialSpeed)
|
|||||||
PROBE_SIMPLE("LC86", "$PQTMVERNO*58", "$PQTMVERNO,LC86", GNSS_MODEL_AG3352, 500);
|
PROBE_SIMPLE("LC86", "$PQTMVERNO*58", "$PQTMVERNO,LC86", GNSS_MODEL_AG3352, 500);
|
||||||
PROBE_SIMPLE("L76K", "$PCAS06,0*1B", "$GPTXT,01,01,02,SW=", GNSS_MODEL_MTK, 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");
|
_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);
|
delay(20);
|
||||||
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
|
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
|
||||||
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
|
{"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);
|
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
|
||||||
|
|
||||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ void tftSetup(void)
|
|||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
tftSleepObserver.observe(¬ifyLightSleep);
|
tftSleepObserver.observe(¬ifyLightSleep);
|
||||||
endSleepObserver.observe(¬ifyLightSleepEnd);
|
endSleepObserver.observe(¬ifyLightSleepEnd);
|
||||||
xTaskCreatePinnedToCore(tft_task_handler, "tft", 8192, NULL, 1, NULL, 0);
|
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
561
src/input/TCA8418Keyboard.cpp
Normal file
561
src/input/TCA8418Keyboard.cpp
Normal file
@@ -0,0 +1,561 @@
|
|||||||
|
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
||||||
|
|
||||||
|
#include "TCA8418Keyboard.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
// REGISTERS
|
||||||
|
// #define _TCA8418_REG_RESERVED 0x00
|
||||||
|
#define _TCA8418_REG_CFG 0x01 // Configuration register
|
||||||
|
#define _TCA8418_REG_INT_STAT 0x02 // Interrupt status
|
||||||
|
#define _TCA8418_REG_KEY_LCK_EC 0x03 // Key lock and event counter
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_A 0x04 // Key event register A
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_B 0x05 // Key event register B
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_C 0x06 // Key event register C
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_D 0x07 // Key event register D
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_E 0x08 // Key event register E
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_F 0x09 // Key event register F
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_G 0x0A // Key event register G
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_H 0x0B // Key event register H
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_I 0x0C // Key event register I
|
||||||
|
#define _TCA8418_REG_KEY_EVENT_J 0x0D // Key event register J
|
||||||
|
#define _TCA8418_REG_KP_LCK_TIMER 0x0E // Keypad lock1 to lock2 timer
|
||||||
|
#define _TCA8418_REG_UNLOCK_1 0x0F // Unlock register 1
|
||||||
|
#define _TCA8418_REG_UNLOCK_2 0x10 // Unlock register 2
|
||||||
|
#define _TCA8418_REG_GPIO_INT_STAT_1 0x11 // GPIO interrupt status 1
|
||||||
|
#define _TCA8418_REG_GPIO_INT_STAT_2 0x12 // GPIO interrupt status 2
|
||||||
|
#define _TCA8418_REG_GPIO_INT_STAT_3 0x13 // GPIO interrupt status 3
|
||||||
|
#define _TCA8418_REG_GPIO_DAT_STAT_1 0x14 // GPIO data status 1
|
||||||
|
#define _TCA8418_REG_GPIO_DAT_STAT_2 0x15 // GPIO data status 2
|
||||||
|
#define _TCA8418_REG_GPIO_DAT_STAT_3 0x16 // GPIO data status 3
|
||||||
|
#define _TCA8418_REG_GPIO_DAT_OUT_1 0x17 // GPIO data out 1
|
||||||
|
#define _TCA8418_REG_GPIO_DAT_OUT_2 0x18 // GPIO data out 2
|
||||||
|
#define _TCA8418_REG_GPIO_DAT_OUT_3 0x19 // GPIO data out 3
|
||||||
|
#define _TCA8418_REG_GPIO_INT_EN_1 0x1A // GPIO interrupt enable 1
|
||||||
|
#define _TCA8418_REG_GPIO_INT_EN_2 0x1B // GPIO interrupt enable 2
|
||||||
|
#define _TCA8418_REG_GPIO_INT_EN_3 0x1C // GPIO interrupt enable 3
|
||||||
|
#define _TCA8418_REG_KP_GPIO_1 0x1D // Keypad/GPIO select 1
|
||||||
|
#define _TCA8418_REG_KP_GPIO_2 0x1E // Keypad/GPIO select 2
|
||||||
|
#define _TCA8418_REG_KP_GPIO_3 0x1F // Keypad/GPIO select 3
|
||||||
|
#define _TCA8418_REG_GPI_EM_1 0x20 // GPI event mode 1
|
||||||
|
#define _TCA8418_REG_GPI_EM_2 0x21 // GPI event mode 2
|
||||||
|
#define _TCA8418_REG_GPI_EM_3 0x22 // GPI event mode 3
|
||||||
|
#define _TCA8418_REG_GPIO_DIR_1 0x23 // GPIO data direction 1
|
||||||
|
#define _TCA8418_REG_GPIO_DIR_2 0x24 // GPIO data direction 2
|
||||||
|
#define _TCA8418_REG_GPIO_DIR_3 0x25 // GPIO data direction 3
|
||||||
|
#define _TCA8418_REG_GPIO_INT_LVL_1 0x26 // GPIO edge/level detect 1
|
||||||
|
#define _TCA8418_REG_GPIO_INT_LVL_2 0x27 // GPIO edge/level detect 2
|
||||||
|
#define _TCA8418_REG_GPIO_INT_LVL_3 0x28 // GPIO edge/level detect 3
|
||||||
|
#define _TCA8418_REG_DEBOUNCE_DIS_1 0x29 // Debounce disable 1
|
||||||
|
#define _TCA8418_REG_DEBOUNCE_DIS_2 0x2A // Debounce disable 2
|
||||||
|
#define _TCA8418_REG_DEBOUNCE_DIS_3 0x2B // Debounce disable 3
|
||||||
|
#define _TCA8418_REG_GPIO_PULL_1 0x2C // GPIO pull-up disable 1
|
||||||
|
#define _TCA8418_REG_GPIO_PULL_2 0x2D // GPIO pull-up disable 2
|
||||||
|
#define _TCA8418_REG_GPIO_PULL_3 0x2E // GPIO pull-up disable 3
|
||||||
|
// #define _TCA8418_REG_RESERVED 0x2F
|
||||||
|
|
||||||
|
// FIELDS CONFIG REGISTER 1
|
||||||
|
#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write
|
||||||
|
#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config
|
||||||
|
#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable
|
||||||
|
#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config
|
||||||
|
#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable
|
||||||
|
#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable
|
||||||
|
#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable
|
||||||
|
#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable
|
||||||
|
|
||||||
|
// FIELDS INT_STAT REGISTER 2
|
||||||
|
#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status
|
||||||
|
#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status
|
||||||
|
#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status
|
||||||
|
#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status
|
||||||
|
#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status
|
||||||
|
|
||||||
|
// FIELDS KEY_LCK_EC REGISTER 3
|
||||||
|
#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable
|
||||||
|
#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2
|
||||||
|
#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0
|
||||||
|
|
||||||
|
// Pin IDs for matrix rows/columns
|
||||||
|
enum {
|
||||||
|
_TCA8418_ROW0, // Pin ID for row 0
|
||||||
|
_TCA8418_ROW1, // Pin ID for row 1
|
||||||
|
_TCA8418_ROW2, // Pin ID for row 2
|
||||||
|
_TCA8418_ROW3, // Pin ID for row 3
|
||||||
|
_TCA8418_ROW4, // Pin ID for row 4
|
||||||
|
_TCA8418_ROW5, // Pin ID for row 5
|
||||||
|
_TCA8418_ROW6, // Pin ID for row 6
|
||||||
|
_TCA8418_ROW7, // Pin ID for row 7
|
||||||
|
_TCA8418_COL0, // Pin ID for column 0
|
||||||
|
_TCA8418_COL1, // Pin ID for column 1
|
||||||
|
_TCA8418_COL2, // Pin ID for column 2
|
||||||
|
_TCA8418_COL3, // Pin ID for column 3
|
||||||
|
_TCA8418_COL4, // Pin ID for column 4
|
||||||
|
_TCA8418_COL5, // Pin ID for column 5
|
||||||
|
_TCA8418_COL6, // Pin ID for column 6
|
||||||
|
_TCA8418_COL7, // Pin ID for column 7
|
||||||
|
_TCA8418_COL8, // Pin ID for column 8
|
||||||
|
_TCA8418_COL9 // Pin ID for column 9
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _TCA8418_COLS 3
|
||||||
|
#define _TCA8418_ROWS 4
|
||||||
|
#define _TCA8418_NUM_KEYS 12
|
||||||
|
|
||||||
|
uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7,
|
||||||
|
9, 7, 9, 2, 2, 2}; // Num chars per key, Modulus for rotating through characters
|
||||||
|
|
||||||
|
unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
|
||||||
|
{'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, // 1
|
||||||
|
{'2', 'a', 'b', 'c', 'A', 'B', 'C'}, // 2
|
||||||
|
{'3', 'd', 'e', 'f', 'D', 'E', 'F'}, // 3
|
||||||
|
{'4', 'g', 'h', 'i', 'G', 'H', 'I'}, // 4
|
||||||
|
{'5', 'j', 'k', 'l', 'J', 'K', 'L'}, // 5
|
||||||
|
{'6', 'm', 'n', 'o', 'M', 'N', 'O'}, // 6
|
||||||
|
{'7', 'p', 'q', 'r', 's', 'P', 'Q', 'R', 'S'}, // 7
|
||||||
|
{'8', 't', 'u', 'v', 'T', 'U', 'V'}, // 8
|
||||||
|
{'9', 'w', 'x', 'y', 'z', 'W', 'X', 'Y', 'Z'}, // 9
|
||||||
|
{'*', '+'}, // *
|
||||||
|
{'0', ' '}, // 0
|
||||||
|
{'#', '@'}, // #
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
|
||||||
|
_TCA8418_ESC, // 1
|
||||||
|
_TCA8418_UP, // 2
|
||||||
|
_TCA8418_NONE, // 3
|
||||||
|
_TCA8418_LEFT, // 4
|
||||||
|
_TCA8418_NONE, // 5
|
||||||
|
_TCA8418_RIGHT, // 6
|
||||||
|
_TCA8418_NONE, // 7
|
||||||
|
_TCA8418_DOWN, // 8
|
||||||
|
_TCA8418_NONE, // 9
|
||||||
|
_TCA8418_BSP, // *
|
||||||
|
_TCA8418_NONE, // 0
|
||||||
|
_TCA8418_NONE, // #
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _TCA8418_LONG_PRESS_THRESHOLD 2000
|
||||||
|
#define _TCA8418_MULTI_TAP_THRESHOLD 750
|
||||||
|
|
||||||
|
TCA8418Keyboard::TCA8418Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
|
||||||
|
{
|
||||||
|
state = Init;
|
||||||
|
last_key = -1;
|
||||||
|
next_key = -1;
|
||||||
|
should_backspace = false;
|
||||||
|
last_tap = 0L;
|
||||||
|
char_idx = 0;
|
||||||
|
tap_interval = 0;
|
||||||
|
backlight_on = true;
|
||||||
|
queue = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::begin(uint8_t addr, TwoWire *wire)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = wire;
|
||||||
|
|
||||||
|
m_wire->begin();
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = nullptr;
|
||||||
|
writeCallback = w;
|
||||||
|
readCallback = r;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::reset()
|
||||||
|
{
|
||||||
|
LOG_DEBUG("TCA8418 Reset");
|
||||||
|
// GPIO
|
||||||
|
// set default all GIO pins to INPUT
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_DIR_1, 0x00);
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_DIR_2, 0x00);
|
||||||
|
// Set COL9 as GPIO output
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x02);
|
||||||
|
// Switch off keyboard backlight (COL9 = LOW)
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
|
||||||
|
|
||||||
|
// add all pins to key events
|
||||||
|
writeRegister(_TCA8418_REG_GPI_EM_1, 0xFF);
|
||||||
|
writeRegister(_TCA8418_REG_GPI_EM_2, 0xFF);
|
||||||
|
writeRegister(_TCA8418_REG_GPI_EM_3, 0xFF);
|
||||||
|
|
||||||
|
// set all pins to FALLING interrupts
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_INT_LVL_1, 0x00);
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_INT_LVL_2, 0x00);
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_INT_LVL_3, 0x00);
|
||||||
|
|
||||||
|
// add all pins to interrupts
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_INT_EN_1, 0xFF);
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_INT_EN_2, 0xFF);
|
||||||
|
writeRegister(_TCA8418_REG_GPIO_INT_EN_3, 0xFF);
|
||||||
|
|
||||||
|
// Set keyboard matrix size
|
||||||
|
matrix(_TCA8418_ROWS, _TCA8418_COLS);
|
||||||
|
enableDebounce();
|
||||||
|
flush();
|
||||||
|
state = Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418Keyboard::matrix(uint8_t rows, uint8_t columns)
|
||||||
|
{
|
||||||
|
if ((rows > 8) || (columns > 10))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Skip zero size matrix
|
||||||
|
if ((rows != 0) && (columns != 0)) {
|
||||||
|
// Setup the keypad matrix.
|
||||||
|
uint8_t mask = 0x00;
|
||||||
|
for (int r = 0; r < rows; r++) {
|
||||||
|
mask <<= 1;
|
||||||
|
mask |= 1;
|
||||||
|
}
|
||||||
|
writeRegister(_TCA8418_REG_KP_GPIO_1, mask);
|
||||||
|
|
||||||
|
mask = 0x00;
|
||||||
|
for (int c = 0; c < columns && c < 8; c++) {
|
||||||
|
mask <<= 1;
|
||||||
|
mask |= 1;
|
||||||
|
}
|
||||||
|
writeRegister(_TCA8418_REG_KP_GPIO_2, mask);
|
||||||
|
|
||||||
|
if (columns > 8) {
|
||||||
|
if (columns == 9)
|
||||||
|
mask = 0x01;
|
||||||
|
else
|
||||||
|
mask = 0x03;
|
||||||
|
writeRegister(_TCA8418_REG_KP_GPIO_3, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418Keyboard::keyCount() const
|
||||||
|
{
|
||||||
|
uint8_t eventCount = readRegister(_TCA8418_REG_KEY_LCK_EC);
|
||||||
|
eventCount &= 0x0F; // lower 4 bits only
|
||||||
|
return eventCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418Keyboard::hasEvent()
|
||||||
|
{
|
||||||
|
return queue.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::queueEvent(char next)
|
||||||
|
{
|
||||||
|
if (next == _TCA8418_NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queue.concat(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
char TCA8418Keyboard::dequeueEvent()
|
||||||
|
{
|
||||||
|
if (queue.length() < 1) {
|
||||||
|
return _TCA8418_NONE;
|
||||||
|
}
|
||||||
|
char next = queue.charAt(0);
|
||||||
|
queue.remove(0, 1);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::trigger()
|
||||||
|
{
|
||||||
|
if (keyCount() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state != Init) {
|
||||||
|
// Read the key register
|
||||||
|
uint8_t k = readRegister(_TCA8418_REG_KEY_EVENT_A);
|
||||||
|
uint8_t key = k & 0x7F;
|
||||||
|
if (k & 0x80) {
|
||||||
|
if (state == Idle)
|
||||||
|
pressed(key);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (state == Held) {
|
||||||
|
released();
|
||||||
|
}
|
||||||
|
state = Idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::pressed(uint8_t key)
|
||||||
|
{
|
||||||
|
if (state == Init || state == Busy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t next_key = 0;
|
||||||
|
int row = (key - 1) / 10;
|
||||||
|
int col = (key - 1) % 10;
|
||||||
|
|
||||||
|
if (row >= _TCA8418_ROWS || col >= _TCA8418_COLS) {
|
||||||
|
return; // Invalid key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute key index based on dynamic row/column
|
||||||
|
next_key = row * _TCA8418_COLS + col;
|
||||||
|
|
||||||
|
// LOG_DEBUG("TCA8418: Key %u -> Next Key %u", key, next_key);
|
||||||
|
|
||||||
|
state = Held;
|
||||||
|
uint32_t now = millis();
|
||||||
|
tap_interval = now - last_tap;
|
||||||
|
if (tap_interval < 0) {
|
||||||
|
// Long running, millis has overflowed.
|
||||||
|
last_tap = 0;
|
||||||
|
state = Busy;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the key is the same as the last one or if the time interval has passed
|
||||||
|
if (next_key != last_key || tap_interval > _TCA8418_MULTI_TAP_THRESHOLD) {
|
||||||
|
char_idx = 0; // Reset char index if new key or long press
|
||||||
|
should_backspace = false; // dont backspace on new key
|
||||||
|
} else {
|
||||||
|
char_idx += 1; // Cycle through characters if same key pressed
|
||||||
|
should_backspace = true; // allow backspace on same key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the current key as the last key
|
||||||
|
last_key = next_key;
|
||||||
|
last_tap = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::released()
|
||||||
|
{
|
||||||
|
if (state != Held) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_key < 0 || last_key > _TCA8418_NUM_KEYS) { // reset to idle if last_key out of bounds
|
||||||
|
last_key = -1;
|
||||||
|
state = Idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t now = millis();
|
||||||
|
int32_t held_interval = now - last_tap;
|
||||||
|
last_tap = now;
|
||||||
|
if (tap_interval < _TCA8418_MULTI_TAP_THRESHOLD && should_backspace) {
|
||||||
|
queueEvent(_TCA8418_BSP);
|
||||||
|
}
|
||||||
|
if (held_interval > _TCA8418_LONG_PRESS_THRESHOLD) {
|
||||||
|
queueEvent(TCA8418LongPressMap[last_key]);
|
||||||
|
// LOG_DEBUG("Long Press Key: %i Map: %i", last_key, TCA8418LongPressMap[last_key]);
|
||||||
|
} else {
|
||||||
|
queueEvent(TCA8418TapMap[last_key][(char_idx % TCA8418TapMod[last_key])]);
|
||||||
|
// LOG_DEBUG("Key Press: %i Index:%i if %i Map: %c", last_key, char_idx, TCA8418TapMod[last_key],
|
||||||
|
// TCA8418TapMap[last_key][(char_idx % TCA8418TapMod[last_key])]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418Keyboard::flush()
|
||||||
|
{
|
||||||
|
// Flush key events
|
||||||
|
uint8_t count = 0;
|
||||||
|
while (readRegister(_TCA8418_REG_KEY_EVENT_A) != 0)
|
||||||
|
count++;
|
||||||
|
// Flush gpio events
|
||||||
|
readRegister(_TCA8418_REG_GPIO_INT_STAT_1);
|
||||||
|
readRegister(_TCA8418_REG_GPIO_INT_STAT_2);
|
||||||
|
readRegister(_TCA8418_REG_GPIO_INT_STAT_3);
|
||||||
|
// Clear INT_STAT register
|
||||||
|
writeRegister(_TCA8418_REG_INT_STAT, 3);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418Keyboard::digitalRead(uint8_t pinnum) const
|
||||||
|
{
|
||||||
|
if (pinnum > _TCA8418_COL9)
|
||||||
|
return 0xFF;
|
||||||
|
|
||||||
|
uint8_t reg = _TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
// Level 0 = low other = high
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (value & mask)
|
||||||
|
return HIGH;
|
||||||
|
return LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418Keyboard::digitalWrite(uint8_t pinnum, uint8_t level)
|
||||||
|
{
|
||||||
|
if (pinnum > _TCA8418_COL9)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t reg = _TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
// Level 0 = low other = high
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (level == LOW)
|
||||||
|
value &= ~mask;
|
||||||
|
else
|
||||||
|
value |= mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418Keyboard::pinMode(uint8_t pinnum, uint8_t mode)
|
||||||
|
{
|
||||||
|
if (pinnum > _TCA8418_COL9)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t idx = pinnum / 8;
|
||||||
|
uint8_t reg = _TCA8418_REG_GPIO_DIR_1 + idx;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
// Mode 0 = input 1 = output
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (mode == OUTPUT)
|
||||||
|
value |= mask;
|
||||||
|
else
|
||||||
|
value &= ~mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
// Pullup 0 = enabled 1 = disabled
|
||||||
|
reg = _TCA8418_REG_GPIO_PULL_1 + idx;
|
||||||
|
value = readRegister(reg);
|
||||||
|
if (mode == INPUT_PULLUP)
|
||||||
|
value &= ~mask;
|
||||||
|
else
|
||||||
|
value |= mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418Keyboard::pinIRQMode(uint8_t pinnum, uint8_t mode)
|
||||||
|
{
|
||||||
|
if (pinnum > _TCA8418_COL9)
|
||||||
|
return false;
|
||||||
|
if ((mode != RISING) && (mode != FALLING))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Mode 0 = falling 1 = rising
|
||||||
|
uint8_t idx = pinnum / 8;
|
||||||
|
uint8_t reg = _TCA8418_REG_GPIO_INT_LVL_1 + idx;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (mode == RISING)
|
||||||
|
value |= mask;
|
||||||
|
else
|
||||||
|
value &= ~mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
// Enable interrupt
|
||||||
|
reg = _TCA8418_REG_GPIO_INT_EN_1 + idx;
|
||||||
|
value = readRegister(reg);
|
||||||
|
value |= mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::enableInterrupts()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||||
|
value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
||||||
|
writeRegister(_TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418Keyboard::disableInterrupts()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||||
|
value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
||||||
|
writeRegister(_TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418Keyboard::enableMatrixOverflow()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||||
|
value |= _TCA8418_REG_CFG_OVR_FLOW_M;
|
||||||
|
writeRegister(_TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418Keyboard::disableMatrixOverflow()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
||||||
|
value &= ~_TCA8418_REG_CFG_OVR_FLOW_M;
|
||||||
|
writeRegister(_TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418Keyboard::enableDebounce()
|
||||||
|
{
|
||||||
|
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0x00);
|
||||||
|
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0x00);
|
||||||
|
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::disableDebounce()
|
||||||
|
{
|
||||||
|
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0xFF);
|
||||||
|
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0xFF);
|
||||||
|
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::setBacklight(bool on)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
digitalWrite(_TCA8418_COL9, HIGH);
|
||||||
|
} else {
|
||||||
|
digitalWrite(_TCA8418_COL9, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418Keyboard::readRegister(uint8_t reg) const
|
||||||
|
{
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(reg);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
|
||||||
|
m_wire->requestFrom(m_addr, (uint8_t)1);
|
||||||
|
if (m_wire->available() < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_wire->read();
|
||||||
|
}
|
||||||
|
if (readCallback) {
|
||||||
|
uint8_t data;
|
||||||
|
readCallback(m_addr, reg, &data, 1);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418Keyboard::writeRegister(uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t data[2];
|
||||||
|
data[0] = reg;
|
||||||
|
data[1] = value;
|
||||||
|
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(data, sizeof(uint8_t) * 2);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
}
|
||||||
|
if (writeCallback) {
|
||||||
|
writeCallback(m_addr, data[0], &(data[1]), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/input/TCA8418Keyboard.h
Normal file
83
src/input/TCA8418Keyboard.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#define _TCA8418_NONE 0x00
|
||||||
|
#define _TCA8418_REBOOT 0x90
|
||||||
|
#define _TCA8418_LEFT 0xb4
|
||||||
|
#define _TCA8418_UP 0xb5
|
||||||
|
#define _TCA8418_DOWN 0xb6
|
||||||
|
#define _TCA8418_RIGHT 0xb7
|
||||||
|
#define _TCA8418_ESC 0x1b
|
||||||
|
#define _TCA8418_BSP 0x08
|
||||||
|
#define _TCA8418_SELECT 0x0d
|
||||||
|
|
||||||
|
class TCA8418Keyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
enum KeyState { Init = 0, Idle, Held, Busy };
|
||||||
|
|
||||||
|
KeyState state;
|
||||||
|
int8_t last_key;
|
||||||
|
int8_t next_key;
|
||||||
|
bool should_backspace;
|
||||||
|
uint32_t last_tap;
|
||||||
|
uint8_t char_idx;
|
||||||
|
int32_t tap_interval;
|
||||||
|
bool backlight_on;
|
||||||
|
|
||||||
|
String queue;
|
||||||
|
|
||||||
|
TCA8418Keyboard();
|
||||||
|
|
||||||
|
void begin(uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS, TwoWire *wire = &Wire);
|
||||||
|
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS);
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
// Configure the size of the keypad.
|
||||||
|
// All other rows and columns are set as inputs.
|
||||||
|
bool matrix(uint8_t rows, uint8_t columns);
|
||||||
|
|
||||||
|
// Flush all events in the FIFO buffer + GPIO events.
|
||||||
|
uint8_t flush(void);
|
||||||
|
|
||||||
|
// Key events available in the internal FIFO buffer.
|
||||||
|
uint8_t keyCount(void) const;
|
||||||
|
|
||||||
|
void trigger(void);
|
||||||
|
void pressed(uint8_t key);
|
||||||
|
void released(void);
|
||||||
|
bool hasEvent(void);
|
||||||
|
char dequeueEvent(void);
|
||||||
|
void queueEvent(char);
|
||||||
|
|
||||||
|
uint8_t digitalRead(uint8_t pinnum) const;
|
||||||
|
bool digitalWrite(uint8_t pinnum, uint8_t level);
|
||||||
|
bool pinMode(uint8_t pinnum, uint8_t mode);
|
||||||
|
bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING
|
||||||
|
|
||||||
|
// enable / disable interrupts for matrix and GPI pins
|
||||||
|
void enableInterrupts();
|
||||||
|
void disableInterrupts();
|
||||||
|
|
||||||
|
// ignore key events when FIFO buffer is full or not.
|
||||||
|
void enableMatrixOverflow();
|
||||||
|
void disableMatrixOverflow();
|
||||||
|
|
||||||
|
// debounce keys.
|
||||||
|
void enableDebounce();
|
||||||
|
void disableDebounce();
|
||||||
|
|
||||||
|
void setBacklight(bool on);
|
||||||
|
|
||||||
|
uint8_t readRegister(uint8_t reg) const;
|
||||||
|
void writeRegister(uint8_t reg, uint8_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TwoWire *m_wire;
|
||||||
|
uint8_t m_addr;
|
||||||
|
i2c_com_fptr_t readCallback;
|
||||||
|
i2c_com_fptr_t writeCallback;
|
||||||
|
};
|
||||||
@@ -12,8 +12,8 @@ void CardKbI2cImpl::init()
|
|||||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
|
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
|
||||||
if (cardkb_found.address == 0x00) {
|
if (cardkb_found.address == 0x00) {
|
||||||
LOG_DEBUG("Rescan for I2C keyboard");
|
LOG_DEBUG("Rescan for I2C keyboard");
|
||||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR};
|
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR, XPOWERS_AXP192_AXP2101_ADDRESS};
|
||||||
uint8_t i2caddr_asize = 4;
|
uint8_t i2caddr_asize = 5;
|
||||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||||
|
|
||||||
#if WIRE_INTERFACES_COUNT == 2
|
#if WIRE_INTERFACES_COUNT == 2
|
||||||
@@ -43,6 +43,10 @@ void CardKbI2cImpl::init()
|
|||||||
// assign an arbitrary value to distinguish from other models
|
// assign an arbitrary value to distinguish from other models
|
||||||
kb_model = 0x37;
|
kb_model = 0x37;
|
||||||
break;
|
break;
|
||||||
|
case ScanI2C::DeviceType::TCA8418KB:
|
||||||
|
// assign an arbitrary value to distinguish from other models
|
||||||
|
kb_model = 0x84;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// use this as default since it's also just zero
|
// use this as default since it's also just zero
|
||||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
||||||
@@ -63,4 +67,4 @@ void CardKbI2cImpl::init()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
inputBroker->registerSource(this);
|
inputBroker->registerSource(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ int32_t KbI2cBase::runOnce()
|
|||||||
if (cardkb_found.address == MPR121_KB_ADDR) {
|
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||||
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
|
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
|
||||||
}
|
}
|
||||||
|
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||||
|
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case ScanI2C::WIRE:
|
case ScanI2C::WIRE:
|
||||||
@@ -55,6 +58,9 @@ int32_t KbI2cBase::runOnce()
|
|||||||
if (cardkb_found.address == MPR121_KB_ADDR) {
|
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||||
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
|
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
|
||||||
}
|
}
|
||||||
|
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||||
|
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ScanI2C::NO_I2C:
|
case ScanI2C::NO_I2C:
|
||||||
default:
|
default:
|
||||||
@@ -163,6 +169,70 @@ int32_t KbI2cBase::runOnce()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x84: { // Adafruit TCA8418
|
||||||
|
TCAKeyboard.trigger();
|
||||||
|
InputEvent e;
|
||||||
|
while (TCAKeyboard.hasEvent()) {
|
||||||
|
char nextEvent = TCAKeyboard.dequeueEvent();
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
e.source = this->_originName;
|
||||||
|
switch (nextEvent) {
|
||||||
|
case _TCA8418_NONE:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case _TCA8418_REBOOT:
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_MSG_REBOOT;
|
||||||
|
break;
|
||||||
|
case _TCA8418_LEFT:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case _TCA8418_UP:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case _TCA8418_DOWN:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case _TCA8418_RIGHT:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case _TCA8418_BSP:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||||
|
e.kbchar = 0x08;
|
||||||
|
break;
|
||||||
|
case _TCA8418_SELECT:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
|
e.kbchar = 0x0d;
|
||||||
|
break;
|
||||||
|
case _TCA8418_ESC:
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||||
|
e.kbchar = 0x1b;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (nextEvent > 127) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = nextEvent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
|
LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0x37: { // MPR121
|
case 0x37: { // MPR121
|
||||||
MPRkeyboard.trigger();
|
MPRkeyboard.trigger();
|
||||||
InputEvent e;
|
InputEvent e;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "BBQ10Keyboard.h"
|
#include "BBQ10Keyboard.h"
|
||||||
#include "InputBroker.h"
|
#include "InputBroker.h"
|
||||||
#include "MPR121Keyboard.h"
|
#include "MPR121Keyboard.h"
|
||||||
|
#include "TCA8418Keyboard.h"
|
||||||
#include "Wire.h"
|
#include "Wire.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
@@ -21,5 +22,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
|||||||
|
|
||||||
BBQ10Keyboard Q10keyboard;
|
BBQ10Keyboard Q10keyboard;
|
||||||
MPR121Keyboard MPRkeyboard;
|
MPR121Keyboard MPRkeyboard;
|
||||||
|
TCA8418Keyboard TCAKeyboard;
|
||||||
bool is_sym = false;
|
bool is_sym = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -568,6 +568,10 @@ void setup()
|
|||||||
// assign an arbitrary value to distinguish from other models
|
// assign an arbitrary value to distinguish from other models
|
||||||
kb_model = 0x37;
|
kb_model = 0x37;
|
||||||
break;
|
break;
|
||||||
|
case ScanI2C::DeviceType::TCA8418KB:
|
||||||
|
// assign an arbitrary value to distinguish from other models
|
||||||
|
kb_model = 0x84;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// use this as default since it's also just zero
|
// use this as default since it's also just zero
|
||||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
||||||
@@ -825,7 +829,9 @@ void setup()
|
|||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
|
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
|
||||||
// onNetworkConnected there
|
// onNetworkConnected there
|
||||||
udpThread->start();
|
if (config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||||
|
udpThread->start();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
service = new MeshService();
|
service = new MeshService();
|
||||||
|
|||||||
@@ -161,10 +161,8 @@ void CryptoEngine::hash(uint8_t *bytes, size_t numBytes)
|
|||||||
|
|
||||||
void CryptoEngine::aesSetKey(const uint8_t *key_bytes, size_t key_len)
|
void CryptoEngine::aesSetKey(const uint8_t *key_bytes, size_t key_len)
|
||||||
{
|
{
|
||||||
if (aes) {
|
delete aes;
|
||||||
delete aes;
|
aes = nullptr;
|
||||||
aes = nullptr;
|
|
||||||
}
|
|
||||||
if (key_len != 0) {
|
if (key_len != 0) {
|
||||||
aes = new AESSmall256();
|
aes = new AESSmall256();
|
||||||
aes->setKey(key_bytes, key_len);
|
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.
|
// Generic implementation of AES-CTR encryption.
|
||||||
void CryptoEngine::encryptAESCtr(CryptoKey _key, uint8_t *_nonce, size_t numBytes, uint8_t *bytes)
|
void CryptoEngine::encryptAESCtr(CryptoKey _key, uint8_t *_nonce, size_t numBytes, uint8_t *bytes)
|
||||||
{
|
{
|
||||||
if (ctr) {
|
delete ctr;
|
||||||
delete ctr;
|
ctr = nullptr;
|
||||||
ctr = nullptr;
|
|
||||||
}
|
|
||||||
if (_key.length == 16)
|
if (_key.length == 16)
|
||||||
ctr = new CTR<AES128>();
|
ctr = new CTR<AES128>();
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -309,7 +309,10 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(toPhoneQueue.enqueue(p, 0));
|
if (toPhoneQueue.enqueue(p, 0) == false) {
|
||||||
|
LOG_CRIT("Failed to queue a packet into toPhoneQueue!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
fromNum++;
|
fromNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +326,10 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
|
|||||||
releaseMqttClientProxyMessageToPool(d);
|
releaseMqttClientProxyMessageToPool(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(toPhoneMqttProxyQueue.enqueue(m, 0));
|
if (toPhoneMqttProxyQueue.enqueue(m, 0) == false) {
|
||||||
|
LOG_CRIT("Failed to queue a packet into toPhoneMqttProxyQueue!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
fromNum++;
|
fromNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +343,10 @@ void MeshService::sendClientNotification(meshtastic_ClientNotification *n)
|
|||||||
releaseClientNotificationToPool(d);
|
releaseClientNotificationToPool(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(toPhoneClientNotificationQueue.enqueue(n, 0));
|
if (toPhoneClientNotificationQueue.enqueue(n, 0) == false) {
|
||||||
|
LOG_CRIT("Failed to queue a notification into toPhoneClientNotificationQueue!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
fromNum++;
|
fromNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -628,6 +628,27 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
|
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
|
||||||
meshtastic_Config_PositionConfig_PositionFlags_DOP | meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW);
|
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
|
#ifdef DISPLAY_FLIP_SCREEN
|
||||||
config.display.flip_screen = true;
|
config.display.flip_screen = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -1437,13 +1458,14 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||||
if (p.public_key.size > 0) {
|
if (p.public_key.size > 0) {
|
||||||
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
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!");
|
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
|
||||||
// we copy the key into the incoming packet, to prevent overwrite
|
LOG_INFO("Public Key set for node, not updating!");
|
||||||
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
// we copy the key into the incoming packet, to prevent overwrite
|
||||||
} else {
|
p.public_key.size = 32;
|
||||||
LOG_INFO("Update Node Pubkey!");
|
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
||||||
}
|
} else if (p.public_key.size > 0) {
|
||||||
|
LOG_INFO("Update Node Pubkey!");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ bool STM32WLE5JCInterface::init()
|
|||||||
{
|
{
|
||||||
RadioLibInterface::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);
|
setTCXOVoltage(1.7);
|
||||||
|
#endif
|
||||||
|
|
||||||
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||||
|
|
||||||
@@ -42,4 +44,4 @@ bool STM32WLE5JCInterface::init()
|
|||||||
return res == RADIOLIB_ERR_NONE;
|
return res == RADIOLIB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ARCH_STM32WL
|
#endif // ARCH_STM32WL
|
||||||
|
|||||||
@@ -235,6 +235,8 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_THINKNODE_M2 = 90,
|
meshtastic_HardwareModel_THINKNODE_M2 = 90,
|
||||||
/* Lilygo T-ETH-Elite */
|
/* Lilygo T-ETH-Elite */
|
||||||
meshtastic_HardwareModel_T_ETH_ELITE = 91,
|
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.
|
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.
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class UdpMulticastThread : public concurrency::OSThread
|
|||||||
void start()
|
void start()
|
||||||
{
|
{
|
||||||
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
|
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
|
||||||
#if !defined(ARCH_PORTDUINO)
|
#ifndef ARCH_PORTDUINO
|
||||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||||
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
|
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
|
||||||
#else
|
#else
|
||||||
@@ -59,7 +59,7 @@ class UdpMulticastThread : public concurrency::OSThread
|
|||||||
if (!mp || !udp) {
|
if (!mp || !udp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if !defined(ARCH_PORTDUINO)
|
#ifndef ARCH_PORTDUINO
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ static void onNetworkConnected()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_UDP_MULTICAST
|
#if HAS_UDP_MULTICAST
|
||||||
if (udpThread) {
|
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||||
udpThread->start();
|
udpThread->start();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
#include "input/SerialKeyboardImpl.h"
|
#include "input/SerialKeyboardImpl.h"
|
||||||
#include "input/TrackballInterruptImpl1.h"
|
#include "input/TrackballInterruptImpl1.h"
|
||||||
#include "input/UpDownInterruptImpl1.h"
|
#include "input/UpDownInterruptImpl1.h"
|
||||||
|
#if !MESHTASTIC_EXCLUDE_I2C
|
||||||
#include "input/cardKbI2cImpl.h"
|
#include "input/cardKbI2cImpl.h"
|
||||||
|
#endif
|
||||||
#include "input/kbMatrixImpl.h"
|
#include "input/kbMatrixImpl.h"
|
||||||
#endif
|
#endif
|
||||||
#if !MESHTASTIC_EXCLUDE_ADMIN
|
#if !MESHTASTIC_EXCLUDE_ADMIN
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ uint32_t packetSequence = 0;
|
|||||||
|
|
||||||
int32_t RangeTestModule::runOnce()
|
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
|
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)
|
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) {
|
if (moduleConfig.range_test.enabled) {
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||||||
// moduleConfig.telemetry.environment_screen_enabled = 1;
|
// moduleConfig.telemetry.environment_screen_enabled = 1;
|
||||||
// moduleConfig.telemetry.environment_update_interval = 15;
|
// 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
|
// 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();
|
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
|
// This is the first time the OSThread library has called this function, so do some setup
|
||||||
firstTime = 0;
|
firstTime = 0;
|
||||||
|
|
||||||
if (moduleConfig.telemetry.environment_measurement_enabled) {
|
if (moduleConfig.telemetry.environment_measurement_enabled || ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) {
|
||||||
LOG_INFO("Environment Telemetry: init");
|
LOG_INFO("Environment Telemetry: init");
|
||||||
#ifdef SENSECAP_INDICATOR
|
#ifdef SENSECAP_INDICATOR
|
||||||
result = indicatorSensor.runOnce();
|
result = indicatorSensor.runOnce();
|
||||||
@@ -178,7 +179,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||||||
return result == UINT32_MAX ? disable() : setStartDelay();
|
return result == UINT32_MAX ? disable() : setStartDelay();
|
||||||
} else {
|
} else {
|
||||||
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
|
// 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();
|
return disable();
|
||||||
} else {
|
} else {
|
||||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE
|
||||||
|
#define ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "ProtobufModule.h"
|
#include "ProtobufModule.h"
|
||||||
|
|||||||
@@ -160,13 +160,11 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
void clean()
|
void clean()
|
||||||
{
|
{
|
||||||
isInitialised = false;
|
isInitialised = false;
|
||||||
if (sensor != nullptr) {
|
delete sensor;
|
||||||
delete sensor;
|
sensor = nullptr;
|
||||||
sensor = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -178,6 +178,8 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_MESH_TAB
|
#define HW_VENDOR meshtastic_HardwareModel_MESH_TAB
|
||||||
#elif defined(T_ETH_ELITE)
|
#elif defined(T_ETH_ELITE)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_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
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
198
src/platform/stm32wl/LittleFS.cpp
Normal file
198
src/platform/stm32wl/LittleFS.cpp
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 hathach for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LittleFS.h"
|
||||||
|
#include "stm32wlxx_hal_flash.h"
|
||||||
|
|
||||||
|
/**********************************************************************************************************************
|
||||||
|
* Macro definitions
|
||||||
|
**********************************************************************************************************************/
|
||||||
|
/** This macro is used to suppress compiler messages about a parameter not being used in a function. */
|
||||||
|
#define LFS_UNUSED(p) (void)((p))
|
||||||
|
|
||||||
|
#define STM32WL_PAGE_SIZE (FLASH_PAGE_SIZE)
|
||||||
|
#define STM32WL_PAGE_COUNT (FLASH_PAGE_NB)
|
||||||
|
#define STM32WL_FLASH_BASE (FLASH_BASE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FLASH_SIZE from stm32wle5xx.h will read the actual FLASH size from the chip.
|
||||||
|
* FLASH_END_ADDR is calculated from FLASH_SIZE.
|
||||||
|
* Use the last 28 KiB of the FLASH
|
||||||
|
*/
|
||||||
|
#define LFS_FLASH_TOTAL_SIZE (14 * 2048) /* needs to be a multiple of LFS_BLOCK_SIZE */
|
||||||
|
#define LFS_BLOCK_SIZE (2048)
|
||||||
|
#define LFS_FLASH_ADDR_END (FLASH_END_ADDR)
|
||||||
|
#define LFS_FLASH_ADDR_BASE (LFS_FLASH_ADDR_END - LFS_FLASH_TOTAL_SIZE + 1)
|
||||||
|
|
||||||
|
#if !CFG_DEBUG
|
||||||
|
#define _LFS_DBG(fmt, ...)
|
||||||
|
#else
|
||||||
|
#define _LFS_DBG(fmt, ...) printf("%s:%d (%s): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// LFS Disk IO
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
|
||||||
|
{
|
||||||
|
LFS_UNUSED(c);
|
||||||
|
|
||||||
|
if (!buffer || !size) {
|
||||||
|
_LFS_DBG("%s Invalid parameter!\r\n", __func__);
|
||||||
|
return LFS_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
|
||||||
|
|
||||||
|
memcpy(buffer, (void *)address, size);
|
||||||
|
|
||||||
|
return LFS_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Program a region in a block. The block must have previously
|
||||||
|
// been erased. Negative error codes are propogated to the user.
|
||||||
|
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||||
|
static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
|
||||||
|
{
|
||||||
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
|
||||||
|
HAL_StatusTypeDef hal_rc = HAL_OK;
|
||||||
|
uint32_t dw_count = size / 8;
|
||||||
|
uint64_t *bufp = (uint64_t *)buffer;
|
||||||
|
|
||||||
|
LFS_UNUSED(c);
|
||||||
|
|
||||||
|
_LFS_DBG("Programming %d bytes/%d doublewords at address 0x%08x/block %d, offset %d.", size, dw_count, address, block, off);
|
||||||
|
if (HAL_FLASH_Unlock() != HAL_OK) {
|
||||||
|
return LFS_ERR_IO;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < dw_count; i++) {
|
||||||
|
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
|
||||||
|
_LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x.\n", address);
|
||||||
|
HAL_FLASH_Lock();
|
||||||
|
return LFS_ERR_INVAL;
|
||||||
|
}
|
||||||
|
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *bufp);
|
||||||
|
if (hal_rc != HAL_OK) {
|
||||||
|
/* Error occurred while writing data in Flash memory.
|
||||||
|
* User can add here some code to deal with this error.
|
||||||
|
*/
|
||||||
|
_LFS_DBG("Program error at (0x%08x), 0x%X, error: 0x%08x\n", address, hal_rc, HAL_FLASH_GetError());
|
||||||
|
}
|
||||||
|
address += 8;
|
||||||
|
bufp += 1;
|
||||||
|
}
|
||||||
|
if (HAL_FLASH_Lock() != HAL_OK) {
|
||||||
|
return LFS_ERR_IO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erase a block. A block must be erased before being programmed.
|
||||||
|
// The state of an erased block is undefined. Negative error codes
|
||||||
|
// are propogated to the user.
|
||||||
|
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||||
|
static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
|
||||||
|
{
|
||||||
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE);
|
||||||
|
HAL_StatusTypeDef hal_rc;
|
||||||
|
FLASH_EraseInitTypeDef EraseInitStruct = {.TypeErase = FLASH_TYPEERASE_PAGES, .Page = 0, .NbPages = 1};
|
||||||
|
uint32_t PAGEError = 0;
|
||||||
|
|
||||||
|
LFS_UNUSED(c);
|
||||||
|
|
||||||
|
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
|
||||||
|
_LFS_DBG("Wanted to erase out of bound of FLASH: 0x%08x.\n", address);
|
||||||
|
return LFS_ERR_INVAL;
|
||||||
|
}
|
||||||
|
/* calculate the absolute page, i.e. what the ST wants */
|
||||||
|
EraseInitStruct.Page = (address - STM32WL_FLASH_BASE) / STM32WL_PAGE_SIZE;
|
||||||
|
_LFS_DBG("Erasing block %d at 0x%08x... ", block, address);
|
||||||
|
HAL_FLASH_Unlock();
|
||||||
|
hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
|
||||||
|
HAL_FLASH_Lock();
|
||||||
|
|
||||||
|
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync the state of the underlying block device. Negative error codes
|
||||||
|
// are propogated to the user.
|
||||||
|
static int _internal_flash_sync(const struct lfs_config *c)
|
||||||
|
{
|
||||||
|
LFS_UNUSED(c);
|
||||||
|
// write function performs no caching. No need for sync.
|
||||||
|
|
||||||
|
return LFS_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct lfs_config _InternalFSConfig = {.context = NULL,
|
||||||
|
|
||||||
|
.read = _internal_flash_read,
|
||||||
|
.prog = _internal_flash_prog,
|
||||||
|
.erase = _internal_flash_erase,
|
||||||
|
.sync = _internal_flash_sync,
|
||||||
|
|
||||||
|
.read_size = LFS_BLOCK_SIZE,
|
||||||
|
.prog_size = LFS_BLOCK_SIZE,
|
||||||
|
.block_size = LFS_BLOCK_SIZE,
|
||||||
|
.block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE,
|
||||||
|
.lookahead = 128,
|
||||||
|
|
||||||
|
.read_buffer = NULL,
|
||||||
|
.prog_buffer = NULL,
|
||||||
|
.lookahead_buffer = NULL,
|
||||||
|
.file_buffer = NULL};
|
||||||
|
|
||||||
|
LittleFS InternalFS;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
//
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
LittleFS::LittleFS(void) : STM32_LittleFS(&_InternalFSConfig) {}
|
||||||
|
|
||||||
|
bool LittleFS::begin(void)
|
||||||
|
{
|
||||||
|
if (FLASH_BASE >= LFS_FLASH_ADDR_BASE) {
|
||||||
|
/* There is not enough space on this device for a filesystem. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// failed to mount, erase all pages then format and mount again
|
||||||
|
if (!STM32_LittleFS::begin()) {
|
||||||
|
// Erase all pages of internal flash region for Filesystem.
|
||||||
|
for (uint32_t addr = LFS_FLASH_ADDR_BASE; addr < (LFS_FLASH_ADDR_END + 1); addr += STM32WL_PAGE_SIZE) {
|
||||||
|
_internal_flash_erase(&_InternalFSConfig, (addr - LFS_FLASH_ADDR_BASE) / STM32WL_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lfs format
|
||||||
|
this->format();
|
||||||
|
|
||||||
|
// mount again if still failed, give up
|
||||||
|
if (!STM32_LittleFS::begin())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
41
src/platform/stm32wl/LittleFS.h
Normal file
41
src/platform/stm32wl/LittleFS.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 hathach for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INTERNALFILESYSTEM_H_
|
||||||
|
#define INTERNALFILESYSTEM_H_
|
||||||
|
|
||||||
|
#include "STM32_LittleFS.h"
|
||||||
|
|
||||||
|
class LittleFS : public STM32_LittleFS
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LittleFS(void);
|
||||||
|
|
||||||
|
// overwrite to also perform low level format (sector erase of whole flash region)
|
||||||
|
bool begin(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern LittleFS InternalFS;
|
||||||
|
|
||||||
|
#endif /* INTERNALFILESYSTEM_H_ */
|
||||||
283
src/platform/stm32wl/STM32_LittleFS.cpp
Normal file
283
src/platform/stm32wl/STM32_LittleFS.cpp
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "STM32_LittleFS.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define memclr(buffer, size) memset(buffer, 0, size)
|
||||||
|
#define varclr(_var) memclr(_var, sizeof(*(_var)))
|
||||||
|
|
||||||
|
using namespace STM32_LittleFS_Namespace;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Implementation
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
STM32_LittleFS::STM32_LittleFS(void) : STM32_LittleFS(NULL) {}
|
||||||
|
|
||||||
|
STM32_LittleFS::STM32_LittleFS(struct lfs_config *cfg)
|
||||||
|
{
|
||||||
|
varclr(&_lfs);
|
||||||
|
_lfs_cfg = cfg;
|
||||||
|
_mounted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
STM32_LittleFS::~STM32_LittleFS() {}
|
||||||
|
|
||||||
|
// Initialize and mount the file system
|
||||||
|
// Return true if mounted successfully else probably corrupted.
|
||||||
|
// User should format the disk and try again
|
||||||
|
bool STM32_LittleFS::begin(struct lfs_config *cfg)
|
||||||
|
{
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
bool ret;
|
||||||
|
// not a loop, just an quick way to short-circuit on error
|
||||||
|
do {
|
||||||
|
if (_mounted) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cfg) {
|
||||||
|
_lfs_cfg = cfg;
|
||||||
|
}
|
||||||
|
if (nullptr == _lfs_cfg) {
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// actually attempt to mount, and log error if one occurs
|
||||||
|
int err = lfs_mount(&_lfs, _lfs_cfg);
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
_mounted = (err == LFS_ERR_OK);
|
||||||
|
ret = _mounted;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tear down and unmount file system
|
||||||
|
void STM32_LittleFS::end(void)
|
||||||
|
{
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
if (_mounted) {
|
||||||
|
_mounted = false;
|
||||||
|
int err = lfs_unmount(&_lfs);
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
(void)err;
|
||||||
|
}
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool STM32_LittleFS::format(void)
|
||||||
|
{
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
int err = LFS_ERR_OK;
|
||||||
|
bool attemptMount = _mounted;
|
||||||
|
// not a loop, just an quick way to short-circuit on error
|
||||||
|
do {
|
||||||
|
// if already mounted: umount first -> format -> remount
|
||||||
|
if (_mounted) {
|
||||||
|
_mounted = false;
|
||||||
|
err = lfs_unmount(&_lfs);
|
||||||
|
if (LFS_ERR_OK != err) {
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = lfs_format(&_lfs, _lfs_cfg);
|
||||||
|
if (LFS_ERR_OK != err) {
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attemptMount) {
|
||||||
|
err = lfs_mount(&_lfs, _lfs_cfg);
|
||||||
|
if (LFS_ERR_OK != err) {
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_mounted = true;
|
||||||
|
}
|
||||||
|
// success!
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return LFS_ERR_OK == err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open a file or folder
|
||||||
|
STM32_LittleFS_Namespace::File STM32_LittleFS::open(char const *filepath, uint8_t mode)
|
||||||
|
{
|
||||||
|
// No lock is required here ... the File() object will synchronize with the mutex provided
|
||||||
|
return STM32_LittleFS_Namespace::File(filepath, mode, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file or folder exists
|
||||||
|
bool STM32_LittleFS::exists(char const *filepath)
|
||||||
|
{
|
||||||
|
struct lfs_info info;
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
bool ret = (0 == lfs_stat(&_lfs, filepath, &info));
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a directory, create intermediate parent if needed
|
||||||
|
bool STM32_LittleFS::mkdir(char const *filepath)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
const char *slash = filepath;
|
||||||
|
if (slash[0] == '/')
|
||||||
|
slash++; // skip root '/'
|
||||||
|
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
// make intermediate parent directory(ies)
|
||||||
|
while (NULL != (slash = strchr(slash, '/'))) {
|
||||||
|
char parent[slash - filepath + 1] = {0};
|
||||||
|
memcpy(parent, filepath, slash - filepath);
|
||||||
|
|
||||||
|
int rc = lfs_mkdir(&_lfs, parent);
|
||||||
|
if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) {
|
||||||
|
PRINT_LFS_ERR(rc);
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
slash++;
|
||||||
|
}
|
||||||
|
// make the final requested directory
|
||||||
|
if (ret) {
|
||||||
|
int rc = lfs_mkdir(&_lfs, filepath);
|
||||||
|
if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) {
|
||||||
|
PRINT_LFS_ERR(rc);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a file
|
||||||
|
bool STM32_LittleFS::remove(char const *filepath)
|
||||||
|
{
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
int err = lfs_remove(&_lfs, filepath);
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return LFS_ERR_OK == err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename a file
|
||||||
|
bool STM32_LittleFS::rename(char const *oldfilepath, char const *newfilepath)
|
||||||
|
{
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
int err = lfs_rename(&_lfs, oldfilepath, newfilepath);
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return LFS_ERR_OK == err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a folder
|
||||||
|
bool STM32_LittleFS::rmdir(char const *filepath)
|
||||||
|
{
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
int err = lfs_remove(&_lfs, filepath);
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return LFS_ERR_OK == err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a folder recursively
|
||||||
|
bool STM32_LittleFS::rmdir_r(char const *filepath)
|
||||||
|
{
|
||||||
|
/* lfs is modified to remove non-empty folder,
|
||||||
|
According to below issue, comment these 2 line won't corrupt filesystem
|
||||||
|
at least when using LFS v1. If moving to LFS v2, see tracked issue
|
||||||
|
to see if issues (such as the orphans in threaded linked list) are resolved.
|
||||||
|
https://github.com/ARMmbed/littlefs/issues/43
|
||||||
|
*/
|
||||||
|
_lockFS();
|
||||||
|
|
||||||
|
int err = lfs_remove(&_lfs, filepath);
|
||||||
|
PRINT_LFS_ERR(err);
|
||||||
|
|
||||||
|
_unlockFS();
|
||||||
|
return LFS_ERR_OK == err;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------- Debug -------------//
|
||||||
|
#if CFG_DEBUG
|
||||||
|
|
||||||
|
const char *dbg_strerr_lfs(int32_t err)
|
||||||
|
{
|
||||||
|
switch (err) {
|
||||||
|
case LFS_ERR_OK:
|
||||||
|
return "LFS_ERR_OK";
|
||||||
|
case LFS_ERR_IO:
|
||||||
|
return "LFS_ERR_IO";
|
||||||
|
case LFS_ERR_CORRUPT:
|
||||||
|
return "LFS_ERR_CORRUPT";
|
||||||
|
case LFS_ERR_NOENT:
|
||||||
|
return "LFS_ERR_NOENT";
|
||||||
|
case LFS_ERR_EXIST:
|
||||||
|
return "LFS_ERR_EXIST";
|
||||||
|
case LFS_ERR_NOTDIR:
|
||||||
|
return "LFS_ERR_NOTDIR";
|
||||||
|
case LFS_ERR_ISDIR:
|
||||||
|
return "LFS_ERR_ISDIR";
|
||||||
|
case LFS_ERR_NOTEMPTY:
|
||||||
|
return "LFS_ERR_NOTEMPTY";
|
||||||
|
case LFS_ERR_BADF:
|
||||||
|
return "LFS_ERR_BADF";
|
||||||
|
case LFS_ERR_INVAL:
|
||||||
|
return "LFS_ERR_INVAL";
|
||||||
|
case LFS_ERR_NOSPC:
|
||||||
|
return "LFS_ERR_NOSPC";
|
||||||
|
case LFS_ERR_NOMEM:
|
||||||
|
return "LFS_ERR_NOMEM";
|
||||||
|
|
||||||
|
default:
|
||||||
|
static char errcode[10];
|
||||||
|
sprintf(errcode, "%ld", err);
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
107
src/platform/stm32wl/STM32_LittleFS.h
Normal file
107
src/platform/stm32wl/STM32_LittleFS.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STM32_LITTLEFS_H_
|
||||||
|
#define STM32_LITTLEFS_H_
|
||||||
|
|
||||||
|
#include <Stream.h>
|
||||||
|
|
||||||
|
// Internal Flash uses ARM Little FileSystem
|
||||||
|
// https://github.com/ARMmbed/littlefs
|
||||||
|
#include "../../freertosinc.h" // tied to FreeRTOS for serialization
|
||||||
|
#include "STM32_LittleFS_File.h"
|
||||||
|
#include "littlefs/lfs.h"
|
||||||
|
|
||||||
|
class STM32_LittleFS
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STM32_LittleFS(void);
|
||||||
|
STM32_LittleFS(struct lfs_config *cfg);
|
||||||
|
virtual ~STM32_LittleFS();
|
||||||
|
|
||||||
|
bool begin(struct lfs_config *cfg = NULL);
|
||||||
|
void end(void);
|
||||||
|
|
||||||
|
// Open the specified file/directory with the supplied mode (e.g. read or
|
||||||
|
// write, etc). Returns a File object for interacting with the file.
|
||||||
|
// Note that currently only one file can be open at a time.
|
||||||
|
STM32_LittleFS_Namespace::File open(char const *filename, uint8_t mode = STM32_LittleFS_Namespace::FILE_O_READ);
|
||||||
|
|
||||||
|
// Methods to determine if the requested file path exists.
|
||||||
|
bool exists(char const *filepath);
|
||||||
|
|
||||||
|
// Create the requested directory hierarchy--if intermediate directories
|
||||||
|
// do not exist they will be created.
|
||||||
|
bool mkdir(char const *filepath);
|
||||||
|
|
||||||
|
// Delete the file.
|
||||||
|
bool remove(char const *filepath);
|
||||||
|
|
||||||
|
// Rename the file.
|
||||||
|
bool rename(char const *oldfilepath, char const *newfilepath);
|
||||||
|
|
||||||
|
// Delete a folder (must be empty)
|
||||||
|
bool rmdir(char const *filepath);
|
||||||
|
|
||||||
|
// Delete a folder (recursively)
|
||||||
|
bool rmdir_r(char const *filepath);
|
||||||
|
|
||||||
|
// format file system
|
||||||
|
bool format(void);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/* INTERNAL USAGE ONLY
|
||||||
|
* Although declare as public, it is meant to be invoked by internal
|
||||||
|
* code. User should not call these directly
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
lfs_t *_getFS(void) { return &_lfs; }
|
||||||
|
void _lockFS(void)
|
||||||
|
{ /* no-op */
|
||||||
|
}
|
||||||
|
void _unlockFS(void)
|
||||||
|
{ /* no-op */
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _mounted;
|
||||||
|
struct lfs_config *_lfs_cfg;
|
||||||
|
lfs_t _lfs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !CFG_DEBUG
|
||||||
|
#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, NULL)
|
||||||
|
#define PRINT_LFS_ERR(_err)
|
||||||
|
#else
|
||||||
|
#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, dbg_strerr_lfs)
|
||||||
|
#define PRINT_LFS_ERR(_err) \
|
||||||
|
do { \
|
||||||
|
if (_err) { \
|
||||||
|
printf("%s:%d, LFS error: %d\n", __FILE__, __LINE__, _err); \
|
||||||
|
} \
|
||||||
|
} while (0) // LFS_ERR are of type int, VERIFY_MESS expects long_int
|
||||||
|
|
||||||
|
const char *dbg_strerr_lfs(int32_t err);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* STM32_LITTLEFS_H_ */
|
||||||
394
src/platform/stm32wl/STM32_LittleFS_File.cpp
Normal file
394
src/platform/stm32wl/STM32_LittleFS_File.cpp
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "STM32_LittleFS.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define rtos_malloc malloc
|
||||||
|
#define rtos_free free
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
using namespace STM32_LittleFS_Namespace;
|
||||||
|
|
||||||
|
File::File(STM32_LittleFS &fs)
|
||||||
|
{
|
||||||
|
_fs = &fs;
|
||||||
|
_is_dir = false;
|
||||||
|
_name[0] = 0;
|
||||||
|
_name[LFS_NAME_MAX] = 0;
|
||||||
|
_dir_path = NULL;
|
||||||
|
|
||||||
|
_dir = NULL;
|
||||||
|
_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
File::File(char const *filename, uint8_t mode, STM32_LittleFS &fs) : File(fs)
|
||||||
|
{
|
||||||
|
// public constructor calls public API open(), which will obtain the mutex
|
||||||
|
this->open(filename, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::_open_file(char const *filepath, uint8_t mode)
|
||||||
|
{
|
||||||
|
int flags = (mode == FILE_O_READ) ? LFS_O_RDONLY : (mode == FILE_O_WRITE) ? (LFS_O_RDWR | LFS_O_CREAT) : 0;
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
_file = (lfs_file_t *)rtos_malloc(sizeof(lfs_file_t));
|
||||||
|
if (!_file)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int rc = lfs_file_open(_fs->_getFS(), _file, filepath, flags);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
// failed to open
|
||||||
|
PRINT_LFS_ERR(rc);
|
||||||
|
// free memory
|
||||||
|
rtos_free(_file);
|
||||||
|
_file = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move to end of file
|
||||||
|
if (mode == FILE_O_WRITE)
|
||||||
|
lfs_file_seek(_fs->_getFS(), _file, 0, LFS_SEEK_END);
|
||||||
|
|
||||||
|
_is_dir = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::_open_dir(char const *filepath)
|
||||||
|
{
|
||||||
|
_dir = (lfs_dir_t *)rtos_malloc(sizeof(lfs_dir_t));
|
||||||
|
if (!_dir)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int rc = lfs_dir_open(_fs->_getFS(), _dir, filepath);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
// failed to open
|
||||||
|
PRINT_LFS_ERR(rc);
|
||||||
|
// free memory
|
||||||
|
rtos_free(_dir);
|
||||||
|
_dir = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_is_dir = true;
|
||||||
|
|
||||||
|
_dir_path = (char *)rtos_malloc(strlen(filepath) + 1);
|
||||||
|
strcpy(_dir_path, filepath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::open(char const *filepath, uint8_t mode)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
ret = this->_open(filepath, mode);
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::_open(char const *filepath, uint8_t mode)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
// close if currently opened
|
||||||
|
if (this->isOpen())
|
||||||
|
_close();
|
||||||
|
|
||||||
|
struct lfs_info info;
|
||||||
|
int rc = lfs_stat(_fs->_getFS(), filepath, &info);
|
||||||
|
|
||||||
|
if (LFS_ERR_OK == rc) {
|
||||||
|
// file existed, open file or directory accordingly
|
||||||
|
ret = (info.type == LFS_TYPE_REG) ? _open_file(filepath, mode) : _open_dir(filepath);
|
||||||
|
} else if (LFS_ERR_NOENT == rc) {
|
||||||
|
// file not existed, only proceed with FILE_O_WRITE mode
|
||||||
|
if (mode == FILE_O_WRITE)
|
||||||
|
ret = _open_file(filepath, mode);
|
||||||
|
} else {
|
||||||
|
PRINT_LFS_ERR(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save bare file name
|
||||||
|
if (ret) {
|
||||||
|
char const *splash = strrchr(filepath, '/');
|
||||||
|
strncpy(_name, splash ? (splash + 1) : filepath, LFS_NAME_MAX);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t File::write(uint8_t ch)
|
||||||
|
{
|
||||||
|
return write(&ch, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t File::write(uint8_t const *buf, size_t size)
|
||||||
|
{
|
||||||
|
lfs_ssize_t wrcount = 0;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
wrcount = lfs_file_write(_fs->_getFS(), _file, buf, size);
|
||||||
|
if (wrcount < 0) {
|
||||||
|
wrcount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return wrcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int File::read(void)
|
||||||
|
{
|
||||||
|
// this thin wrapper relies on called function to synchronize
|
||||||
|
int ret = -1;
|
||||||
|
uint8_t ch;
|
||||||
|
if (read(&ch, 1) > 0) {
|
||||||
|
ret = static_cast<int>(ch);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int File::read(void *buf, uint16_t nbyte)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
ret = lfs_file_read(_fs->_getFS(), _file, buf, nbyte);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int File::peek(void)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
uint32_t pos = lfs_file_tell(_fs->_getFS(), _file);
|
||||||
|
uint8_t ch = 0;
|
||||||
|
if (lfs_file_read(_fs->_getFS(), _file, &ch, 1) > 0) {
|
||||||
|
ret = static_cast<int>(ch);
|
||||||
|
}
|
||||||
|
(void)lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int File::available(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
uint32_t size = lfs_file_size(_fs->_getFS(), _file);
|
||||||
|
uint32_t pos = lfs_file_tell(_fs->_getFS(), _file);
|
||||||
|
ret = size - pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::seek(uint32_t pos)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
ret = lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t File::position(void)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
ret = lfs_file_tell(_fs->_getFS(), _file);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t File::size(void)
|
||||||
|
{
|
||||||
|
uint32_t ret = 0;
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
ret = lfs_file_size(_fs->_getFS(), _file);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::truncate(uint32_t pos)
|
||||||
|
{
|
||||||
|
int32_t ret = LFS_ERR_ISDIR;
|
||||||
|
_fs->_lockFS();
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
ret = lfs_file_truncate(_fs->_getFS(), _file, pos);
|
||||||
|
}
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::truncate(void)
|
||||||
|
{
|
||||||
|
int32_t ret = LFS_ERR_ISDIR;
|
||||||
|
uint32_t pos;
|
||||||
|
_fs->_lockFS();
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
pos = lfs_file_tell(_fs->_getFS(), _file);
|
||||||
|
ret = lfs_file_truncate(_fs->_getFS(), _file, pos);
|
||||||
|
}
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void File::flush(void)
|
||||||
|
{
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
if (!this->_is_dir) {
|
||||||
|
lfs_file_sync(_fs->_getFS(), _file);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void File::close(void)
|
||||||
|
{
|
||||||
|
_fs->_lockFS();
|
||||||
|
this->_close();
|
||||||
|
_fs->_unlockFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void File::_close(void)
|
||||||
|
{
|
||||||
|
if (this->isOpen()) {
|
||||||
|
if (this->_is_dir) {
|
||||||
|
lfs_dir_close(_fs->_getFS(), _dir);
|
||||||
|
rtos_free(_dir);
|
||||||
|
_dir = NULL;
|
||||||
|
|
||||||
|
if (this->_dir_path)
|
||||||
|
rtos_free(_dir_path);
|
||||||
|
_dir_path = NULL;
|
||||||
|
} else {
|
||||||
|
lfs_file_close(this->_fs->_getFS(), _file);
|
||||||
|
rtos_free(_file);
|
||||||
|
_file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File::operator bool(void)
|
||||||
|
{
|
||||||
|
return isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::isOpen(void)
|
||||||
|
{
|
||||||
|
return (_file != NULL) || (_dir != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARNING -- although marked as `const`, the values pointed
|
||||||
|
// to may change. For example, if the same File
|
||||||
|
// object has `open()` called with a different
|
||||||
|
// file or directory name, this same pointer will
|
||||||
|
// suddenly (unexpectedly?) have different values.
|
||||||
|
char const *File::name(void)
|
||||||
|
{
|
||||||
|
return this->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::isDirectory(void)
|
||||||
|
{
|
||||||
|
return this->_is_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
File File::openNextFile(uint8_t mode)
|
||||||
|
{
|
||||||
|
_fs->_lockFS();
|
||||||
|
|
||||||
|
File ret(*_fs);
|
||||||
|
if (this->_is_dir) {
|
||||||
|
struct lfs_info info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
// lfs_dir_read returns 0 when reaching end of directory, 1 if found an entry
|
||||||
|
// Skip the "." and ".." entries ...
|
||||||
|
do {
|
||||||
|
rc = lfs_dir_read(_fs->_getFS(), _dir, &info);
|
||||||
|
} while (rc == 1 && (!strcmp(".", info.name) || !strcmp("..", info.name)));
|
||||||
|
|
||||||
|
if (rc == 1) {
|
||||||
|
// string cat name with current folder
|
||||||
|
char filepath[strlen(_dir_path) + 1 + strlen(info.name) + 1]; // potential for significant stack usage
|
||||||
|
strcpy(filepath, _dir_path);
|
||||||
|
if (!(_dir_path[0] == '/' && _dir_path[1] == 0))
|
||||||
|
strcat(filepath, "/"); // only add '/' if cwd is not root
|
||||||
|
strcat(filepath, info.name);
|
||||||
|
|
||||||
|
(void)ret._open(filepath, mode); // return value is ignored ... caller is expected to check isOpened()
|
||||||
|
} else if (rc < 0) {
|
||||||
|
PRINT_LFS_ERR(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_fs->_unlockFS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void File::rewindDirectory(void)
|
||||||
|
{
|
||||||
|
_fs->_lockFS();
|
||||||
|
if (this->_is_dir) {
|
||||||
|
lfs_dir_rewind(_fs->_getFS(), _dir);
|
||||||
|
}
|
||||||
|
_fs->_unlockFS();
|
||||||
|
}
|
||||||
108
src/platform/stm32wl/STM32_LittleFS_File.h
Normal file
108
src/platform/stm32wl/STM32_LittleFS_File.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STM32_LITTLEFS_FILE_H_
|
||||||
|
#define STM32_LITTLEFS_FILE_H_
|
||||||
|
|
||||||
|
#include "littlefs/lfs.h"
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
class STM32_LittleFS;
|
||||||
|
|
||||||
|
namespace STM32_LittleFS_Namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
// avoid conflict with other FileSystem FILE_READ/FILE_WRITE
|
||||||
|
enum {
|
||||||
|
FILE_O_READ = 0,
|
||||||
|
FILE_O_WRITE = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
class File : public Stream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
File(STM32_LittleFS &fs);
|
||||||
|
File(char const *filename, uint8_t mode, STM32_LittleFS &fs);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool open(char const *filename, uint8_t mode);
|
||||||
|
|
||||||
|
//------------- Stream API -------------//
|
||||||
|
virtual size_t write(uint8_t ch);
|
||||||
|
virtual size_t write(uint8_t const *buf, size_t size);
|
||||||
|
size_t write(const char *str)
|
||||||
|
{
|
||||||
|
if (str == NULL)
|
||||||
|
return 0;
|
||||||
|
return write((const uint8_t *)str, strlen(str));
|
||||||
|
}
|
||||||
|
size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); }
|
||||||
|
|
||||||
|
virtual int read(void);
|
||||||
|
int read(void *buf, uint16_t nbyte);
|
||||||
|
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual int available(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
|
||||||
|
bool seek(uint32_t pos);
|
||||||
|
uint32_t position(void);
|
||||||
|
uint32_t size(void);
|
||||||
|
|
||||||
|
bool truncate(uint32_t pos);
|
||||||
|
bool truncate(void);
|
||||||
|
|
||||||
|
void close(void);
|
||||||
|
|
||||||
|
operator bool(void);
|
||||||
|
|
||||||
|
bool isOpen(void);
|
||||||
|
char const *name(void);
|
||||||
|
|
||||||
|
bool isDirectory(void);
|
||||||
|
File openNextFile(uint8_t mode = FILE_O_READ);
|
||||||
|
void rewindDirectory(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
STM32_LittleFS *_fs;
|
||||||
|
|
||||||
|
bool _is_dir;
|
||||||
|
|
||||||
|
union {
|
||||||
|
lfs_file_t *_file;
|
||||||
|
lfs_dir_t *_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *_dir_path;
|
||||||
|
char _name[LFS_NAME_MAX + 1];
|
||||||
|
|
||||||
|
bool _open(char const *filepath, uint8_t mode);
|
||||||
|
bool _open_file(char const *filepath, uint8_t mode);
|
||||||
|
bool _open_dir(char const *filepath);
|
||||||
|
void _close(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace STM32_LittleFS_Namespace
|
||||||
|
|
||||||
|
#endif /* STM32_LITTLEFS_FILE_H_ */
|
||||||
2531
src/platform/stm32wl/littlefs/lfs.c
Normal file
2531
src/platform/stm32wl/littlefs/lfs.c
Normal file
File diff suppressed because it is too large
Load Diff
476
src/platform/stm32wl/littlefs/lfs.h
Normal file
476
src/platform/stm32wl/littlefs/lfs.h
Normal file
@@ -0,0 +1,476 @@
|
|||||||
|
/*
|
||||||
|
* The little filesystem
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef LFS_H
|
||||||
|
#define LFS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Version info ///
|
||||||
|
|
||||||
|
// Software library version
|
||||||
|
// Major (top-nibble), incremented on backwards incompatible changes
|
||||||
|
// Minor (bottom-nibble), incremented on feature additions
|
||||||
|
#define LFS_VERSION 0x00010006
|
||||||
|
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
||||||
|
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
||||||
|
|
||||||
|
// Version of On-disk data structures
|
||||||
|
// Major (top-nibble), incremented on backwards incompatible changes
|
||||||
|
// Minor (bottom-nibble), incremented on feature additions
|
||||||
|
#define LFS_DISK_VERSION 0x00010001
|
||||||
|
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
||||||
|
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
||||||
|
|
||||||
|
/// Definitions ///
|
||||||
|
|
||||||
|
// Type definitions
|
||||||
|
typedef uint32_t lfs_size_t;
|
||||||
|
typedef uint32_t lfs_off_t;
|
||||||
|
|
||||||
|
typedef int32_t lfs_ssize_t;
|
||||||
|
typedef int32_t lfs_soff_t;
|
||||||
|
|
||||||
|
typedef uint32_t lfs_block_t;
|
||||||
|
|
||||||
|
// Max name size in bytes
|
||||||
|
#ifndef LFS_NAME_MAX
|
||||||
|
#define LFS_NAME_MAX 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Possible error codes, these are negative to allow
|
||||||
|
// valid positive return values
|
||||||
|
enum lfs_error {
|
||||||
|
LFS_ERR_OK = 0, // No error
|
||||||
|
LFS_ERR_IO = -5, // Error during device operation
|
||||||
|
LFS_ERR_CORRUPT = -52, // Corrupted
|
||||||
|
LFS_ERR_NOENT = -2, // No directory entry
|
||||||
|
LFS_ERR_EXIST = -17, // Entry already exists
|
||||||
|
LFS_ERR_NOTDIR = -20, // Entry is not a dir
|
||||||
|
LFS_ERR_ISDIR = -21, // Entry is a dir
|
||||||
|
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
|
||||||
|
LFS_ERR_BADF = -9, // Bad file number
|
||||||
|
LFS_ERR_INVAL = -22, // Invalid parameter
|
||||||
|
LFS_ERR_NOSPC = -28, // No space left on device
|
||||||
|
LFS_ERR_NOMEM = -12, // No more memory available
|
||||||
|
};
|
||||||
|
|
||||||
|
// File types
|
||||||
|
enum lfs_type {
|
||||||
|
LFS_TYPE_REG = 0x11,
|
||||||
|
LFS_TYPE_DIR = 0x22,
|
||||||
|
LFS_TYPE_SUPERBLOCK = 0x2e,
|
||||||
|
};
|
||||||
|
|
||||||
|
// File open flags
|
||||||
|
enum lfs_open_flags {
|
||||||
|
// open flags
|
||||||
|
LFS_O_RDONLY = 1, // Open a file as read only
|
||||||
|
LFS_O_WRONLY = 2, // Open a file as write only
|
||||||
|
LFS_O_RDWR = 3, // Open a file as read and write
|
||||||
|
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
||||||
|
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
||||||
|
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
||||||
|
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
||||||
|
|
||||||
|
// internally used flags
|
||||||
|
LFS_F_DIRTY = 0x10000, // File does not match storage
|
||||||
|
LFS_F_WRITING = 0x20000, // File has been written since last flush
|
||||||
|
LFS_F_READING = 0x40000, // File has been read since last flush
|
||||||
|
LFS_F_ERRED = 0x80000, // An error occured during write
|
||||||
|
};
|
||||||
|
|
||||||
|
// File seek flags
|
||||||
|
enum lfs_whence_flags {
|
||||||
|
LFS_SEEK_SET = 0, // Seek relative to an absolute position
|
||||||
|
LFS_SEEK_CUR = 1, // Seek relative to the current file position
|
||||||
|
LFS_SEEK_END = 2, // Seek relative to the end of the file
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configuration provided during initialization of the littlefs
|
||||||
|
struct lfs_config {
|
||||||
|
// Opaque user provided context that can be used to pass
|
||||||
|
// information to the block device operations
|
||||||
|
void *context;
|
||||||
|
|
||||||
|
// Read a region in a block. Negative error codes are propogated
|
||||||
|
// to the user.
|
||||||
|
int (*read)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
|
// Program a region in a block. The block must have previously
|
||||||
|
// been erased. Negative error codes are propogated to the user.
|
||||||
|
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||||
|
int (*prog)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
|
// Erase a block. A block must be erased before being programmed.
|
||||||
|
// The state of an erased block is undefined. Negative error codes
|
||||||
|
// are propogated to the user.
|
||||||
|
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||||
|
int (*erase)(const struct lfs_config *c, lfs_block_t block);
|
||||||
|
|
||||||
|
// Sync the state of the underlying block device. Negative error codes
|
||||||
|
// are propogated to the user.
|
||||||
|
int (*sync)(const struct lfs_config *c);
|
||||||
|
|
||||||
|
// Minimum size of a block read. This determines the size of read buffers.
|
||||||
|
// This may be larger than the physical read size to improve performance
|
||||||
|
// by caching more of the block device.
|
||||||
|
lfs_size_t read_size;
|
||||||
|
|
||||||
|
// Minimum size of a block program. This determines the size of program
|
||||||
|
// buffers. This may be larger than the physical program size to improve
|
||||||
|
// performance by caching more of the block device.
|
||||||
|
// Must be a multiple of the read size.
|
||||||
|
lfs_size_t prog_size;
|
||||||
|
|
||||||
|
// Size of an erasable block. This does not impact ram consumption and
|
||||||
|
// may be larger than the physical erase size. However, this should be
|
||||||
|
// kept small as each file currently takes up an entire block.
|
||||||
|
// Must be a multiple of the program size.
|
||||||
|
lfs_size_t block_size;
|
||||||
|
|
||||||
|
// Number of erasable blocks on the device.
|
||||||
|
lfs_size_t block_count;
|
||||||
|
|
||||||
|
// Number of blocks to lookahead during block allocation. A larger
|
||||||
|
// lookahead reduces the number of passes required to allocate a block.
|
||||||
|
// The lookahead buffer requires only 1 bit per block so it can be quite
|
||||||
|
// large with little ram impact. Should be a multiple of 32.
|
||||||
|
lfs_size_t lookahead;
|
||||||
|
|
||||||
|
// Optional, statically allocated read buffer. Must be read sized.
|
||||||
|
void *read_buffer;
|
||||||
|
|
||||||
|
// Optional, statically allocated program buffer. Must be program sized.
|
||||||
|
void *prog_buffer;
|
||||||
|
|
||||||
|
// Optional, statically allocated lookahead buffer. Must be 1 bit per
|
||||||
|
// lookahead block.
|
||||||
|
void *lookahead_buffer;
|
||||||
|
|
||||||
|
// Optional, statically allocated buffer for files. Must be program sized.
|
||||||
|
// If enabled, only one file may be opened at a time.
|
||||||
|
void *file_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optional configuration provided during lfs_file_opencfg
|
||||||
|
struct lfs_file_config {
|
||||||
|
// Optional, statically allocated buffer for files. Must be program sized.
|
||||||
|
// If NULL, malloc will be used by default.
|
||||||
|
void *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
// File info structure
|
||||||
|
struct lfs_info {
|
||||||
|
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
|
// Size of the file, only valid for REG files
|
||||||
|
lfs_size_t size;
|
||||||
|
|
||||||
|
// Name of the file stored as a null-terminated string
|
||||||
|
char name[LFS_NAME_MAX + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
/// littlefs data structures ///
|
||||||
|
typedef struct lfs_entry {
|
||||||
|
lfs_off_t off;
|
||||||
|
|
||||||
|
struct lfs_disk_entry {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t elen;
|
||||||
|
uint8_t alen;
|
||||||
|
uint8_t nlen;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
lfs_block_t head;
|
||||||
|
lfs_size_t size;
|
||||||
|
} file;
|
||||||
|
lfs_block_t dir[2];
|
||||||
|
} u;
|
||||||
|
} d;
|
||||||
|
} lfs_entry_t;
|
||||||
|
|
||||||
|
typedef struct lfs_cache {
|
||||||
|
lfs_block_t block;
|
||||||
|
lfs_off_t off;
|
||||||
|
uint8_t *buffer;
|
||||||
|
} lfs_cache_t;
|
||||||
|
|
||||||
|
typedef struct lfs_file {
|
||||||
|
struct lfs_file *next;
|
||||||
|
lfs_block_t pair[2];
|
||||||
|
lfs_off_t poff;
|
||||||
|
|
||||||
|
lfs_block_t head;
|
||||||
|
lfs_size_t size;
|
||||||
|
|
||||||
|
const struct lfs_file_config *cfg;
|
||||||
|
uint32_t flags;
|
||||||
|
lfs_off_t pos;
|
||||||
|
lfs_block_t block;
|
||||||
|
lfs_off_t off;
|
||||||
|
lfs_cache_t cache;
|
||||||
|
} lfs_file_t;
|
||||||
|
|
||||||
|
typedef struct lfs_dir {
|
||||||
|
struct lfs_dir *next;
|
||||||
|
lfs_block_t pair[2];
|
||||||
|
lfs_off_t off;
|
||||||
|
|
||||||
|
lfs_block_t head[2];
|
||||||
|
lfs_off_t pos;
|
||||||
|
|
||||||
|
struct lfs_disk_dir {
|
||||||
|
uint32_t rev;
|
||||||
|
lfs_size_t size;
|
||||||
|
lfs_block_t tail[2];
|
||||||
|
} d;
|
||||||
|
} lfs_dir_t;
|
||||||
|
|
||||||
|
typedef struct lfs_superblock {
|
||||||
|
lfs_off_t off;
|
||||||
|
|
||||||
|
struct lfs_disk_superblock {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t elen;
|
||||||
|
uint8_t alen;
|
||||||
|
uint8_t nlen;
|
||||||
|
lfs_block_t root[2];
|
||||||
|
uint32_t block_size;
|
||||||
|
uint32_t block_count;
|
||||||
|
uint32_t version;
|
||||||
|
char magic[8];
|
||||||
|
} d;
|
||||||
|
} lfs_superblock_t;
|
||||||
|
|
||||||
|
typedef struct lfs_free {
|
||||||
|
lfs_block_t off;
|
||||||
|
lfs_block_t size;
|
||||||
|
lfs_block_t i;
|
||||||
|
lfs_block_t ack;
|
||||||
|
uint32_t *buffer;
|
||||||
|
} lfs_free_t;
|
||||||
|
|
||||||
|
// The littlefs type
|
||||||
|
typedef struct lfs {
|
||||||
|
const struct lfs_config *cfg;
|
||||||
|
|
||||||
|
lfs_block_t root[2];
|
||||||
|
lfs_file_t *files;
|
||||||
|
lfs_dir_t *dirs;
|
||||||
|
|
||||||
|
lfs_cache_t rcache;
|
||||||
|
lfs_cache_t pcache;
|
||||||
|
|
||||||
|
lfs_free_t free;
|
||||||
|
bool deorphaned;
|
||||||
|
} lfs_t;
|
||||||
|
|
||||||
|
/// Filesystem functions ///
|
||||||
|
|
||||||
|
// Format a block device with the littlefs
|
||||||
|
//
|
||||||
|
// Requires a littlefs object and config struct. This clobbers the littlefs
|
||||||
|
// object, and does not leave the filesystem mounted. The config struct must
|
||||||
|
// be zeroed for defaults and backwards compatibility.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
||||||
|
|
||||||
|
// Mounts a littlefs
|
||||||
|
//
|
||||||
|
// Requires a littlefs object and config struct. Multiple filesystems
|
||||||
|
// may be mounted simultaneously with multiple littlefs objects. Both
|
||||||
|
// lfs and config must be allocated while mounted. The config struct must
|
||||||
|
// be zeroed for defaults and backwards compatibility.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
||||||
|
|
||||||
|
// Unmounts a littlefs
|
||||||
|
//
|
||||||
|
// Does nothing besides releasing any allocated resources.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_unmount(lfs_t *lfs);
|
||||||
|
|
||||||
|
/// General operations ///
|
||||||
|
|
||||||
|
// Removes a file or directory
|
||||||
|
//
|
||||||
|
// If removing a directory, the directory must be empty.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_remove(lfs_t *lfs, const char *path);
|
||||||
|
|
||||||
|
// Rename or move a file or directory
|
||||||
|
//
|
||||||
|
// If the destination exists, it must match the source in type.
|
||||||
|
// If the destination is a directory, the directory must be empty.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
|
||||||
|
|
||||||
|
// Find info about a file or directory
|
||||||
|
//
|
||||||
|
// Fills out the info structure, based on the specified file or directory.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
||||||
|
|
||||||
|
/// File operations ///
|
||||||
|
|
||||||
|
// Open a file
|
||||||
|
//
|
||||||
|
// The mode that the file is opened in is determined by the flags, which
|
||||||
|
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags);
|
||||||
|
|
||||||
|
// Open a file with extra configuration
|
||||||
|
//
|
||||||
|
// The mode that the file is opened in is determined by the flags, which
|
||||||
|
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||||
|
//
|
||||||
|
// The config struct provides additional config options per file as described
|
||||||
|
// above. The config struct must be allocated while the file is open, and the
|
||||||
|
// config struct must be zeroed for defaults and backwards compatibility.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, const char *path, int flags, const struct lfs_file_config *config);
|
||||||
|
|
||||||
|
// Close a file
|
||||||
|
//
|
||||||
|
// Any pending writes are written out to storage as though
|
||||||
|
// sync had been called and releases any allocated resources.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
|
||||||
|
// Synchronize a file on storage
|
||||||
|
//
|
||||||
|
// Any pending writes are written out to storage.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
|
||||||
|
// Read data from file
|
||||||
|
//
|
||||||
|
// Takes a buffer and size indicating where to store the read data.
|
||||||
|
// Returns the number of bytes read, or a negative error code on failure.
|
||||||
|
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
|
// Write data to file
|
||||||
|
//
|
||||||
|
// Takes a buffer and size indicating the data to write. The file will not
|
||||||
|
// actually be updated on the storage until either sync or close is called.
|
||||||
|
//
|
||||||
|
// Returns the number of bytes written, or a negative error code on failure.
|
||||||
|
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, const void *buffer, lfs_size_t size);
|
||||||
|
|
||||||
|
// Change the position of the file
|
||||||
|
//
|
||||||
|
// The change in position is determined by the offset and whence flag.
|
||||||
|
// Returns the old position of the file, or a negative error code on failure.
|
||||||
|
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, lfs_soff_t off, int whence);
|
||||||
|
|
||||||
|
// Truncates the size of the file to the specified size
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
|
||||||
|
|
||||||
|
// Return the position of the file
|
||||||
|
//
|
||||||
|
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||||
|
// Returns the position of the file, or a negative error code on failure.
|
||||||
|
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
|
||||||
|
// Change the position of the file to the beginning of the file
|
||||||
|
//
|
||||||
|
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
|
||||||
|
// Return the size of the file
|
||||||
|
//
|
||||||
|
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
|
||||||
|
// Returns the size of the file, or a negative error code on failure.
|
||||||
|
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
|
||||||
|
/// Directory operations ///
|
||||||
|
|
||||||
|
// Create a directory
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_mkdir(lfs_t *lfs, const char *path);
|
||||||
|
|
||||||
|
// Open a directory
|
||||||
|
//
|
||||||
|
// Once open a directory can be used with read to iterate over files.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
|
||||||
|
|
||||||
|
// Close a directory
|
||||||
|
//
|
||||||
|
// Releases any allocated resources.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
|
||||||
|
|
||||||
|
// Read an entry in the directory
|
||||||
|
//
|
||||||
|
// Fills out the info structure, based on the specified file or directory.
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
|
||||||
|
|
||||||
|
// Change the position of the directory
|
||||||
|
//
|
||||||
|
// The new off must be a value previous returned from tell and specifies
|
||||||
|
// an absolute offset in the directory seek.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
|
||||||
|
|
||||||
|
// Return the position of the directory
|
||||||
|
//
|
||||||
|
// The returned offset is only meant to be consumed by seek and may not make
|
||||||
|
// sense, but does indicate the current position in the directory iteration.
|
||||||
|
//
|
||||||
|
// Returns the position of the directory, or a negative error code on failure.
|
||||||
|
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
|
||||||
|
|
||||||
|
// Change the position of the directory to the beginning of the directory
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
||||||
|
|
||||||
|
/// Miscellaneous littlefs specific operations ///
|
||||||
|
|
||||||
|
// Traverse through all blocks in use by the filesystem
|
||||||
|
//
|
||||||
|
// The provided callback will be called with each block address that is
|
||||||
|
// currently in use by the filesystem. This can be used to determine which
|
||||||
|
// blocks are in use or how much of the storage is available.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data);
|
||||||
|
|
||||||
|
// Prunes any recoverable errors that may have occured in the filesystem
|
||||||
|
//
|
||||||
|
// Not needed to be called by user unless an operation is interrupted
|
||||||
|
// but the filesystem is still mounted. This is already called on first
|
||||||
|
// allocation.
|
||||||
|
//
|
||||||
|
// Returns a negative error code on failure.
|
||||||
|
int lfs_deorphan(lfs_t *lfs);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
28
src/platform/stm32wl/littlefs/lfs_util.c
Normal file
28
src/platform/stm32wl/littlefs/lfs_util.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* lfs util functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#include "lfs_util.h"
|
||||||
|
|
||||||
|
// Only compile if user does not provide custom config
|
||||||
|
#ifndef LFS_CONFIG
|
||||||
|
|
||||||
|
// Software CRC implementation with small lookup table
|
||||||
|
void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
static const uint32_t rtable[16] = {
|
||||||
|
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||||
|
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t *data = buffer;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf];
|
||||||
|
*crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
199
src/platform/stm32wl/littlefs/lfs_util.h
Normal file
199
src/platform/stm32wl/littlefs/lfs_util.h
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* lfs utility functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef LFS_UTIL_H
|
||||||
|
#define LFS_UTIL_H
|
||||||
|
|
||||||
|
// Users can override lfs_util.h with their own configuration by defining
|
||||||
|
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
|
||||||
|
//
|
||||||
|
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
|
||||||
|
// provided by the config file. To start I would suggest copying lfs_util.h and
|
||||||
|
// modifying as needed.
|
||||||
|
#ifdef LFS_CONFIG
|
||||||
|
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
|
||||||
|
#define LFS_STRINGIZE2(x) #x
|
||||||
|
#include LFS_STRINGIZE(LFS_CONFIG)
|
||||||
|
#else
|
||||||
|
|
||||||
|
// System includes
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifndef LFS_NO_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !CFG_DEBUG
|
||||||
|
#define LFS_NO_DEBUG
|
||||||
|
#define LFS_NO_WARN
|
||||||
|
#define LFS_NO_ERROR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macros, may be replaced by system specific wrappers. Arguments to these
|
||||||
|
// macros must not have side-effects as the macros can be removed for a smaller
|
||||||
|
// code footprint
|
||||||
|
|
||||||
|
// Logging functions
|
||||||
|
#ifndef LFS_NO_DEBUG
|
||||||
|
#define LFS_DEBUG(fmt, ...) printf("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_DEBUG(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LFS_NO_WARN
|
||||||
|
#define LFS_WARN(fmt, ...) printf("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_WARN(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LFS_NO_ERROR
|
||||||
|
#define LFS_ERROR(fmt, ...) printf("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_ERROR(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Runtime assertions
|
||||||
|
#ifndef LFS_NO_ASSERT
|
||||||
|
#define LFS_ASSERT(test) assert(test)
|
||||||
|
#else
|
||||||
|
#define LFS_ASSERT(test)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Builtin functions, these may be replaced by more efficient
|
||||||
|
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||||
|
// expensive basic C implementation for debugging purposes
|
||||||
|
|
||||||
|
// Min/max functions for unsigned 32-bit numbers
|
||||||
|
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next smallest power of 2 less than or equal to a
|
||||||
|
static inline uint32_t lfs_npw2(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||||
|
return 32 - __builtin_clz(a - 1);
|
||||||
|
#else
|
||||||
|
uint32_t r = 0;
|
||||||
|
uint32_t s;
|
||||||
|
a -= 1;
|
||||||
|
s = (a > 0xffff) << 4;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
s = (a > 0xff) << 3;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
s = (a > 0xf) << 2;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
s = (a > 0x3) << 1;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
return (r | (a >> 1)) + 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of trailing binary zeros in a
|
||||||
|
// lfs_ctz(0) may be undefined
|
||||||
|
static inline uint32_t lfs_ctz(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||||
|
return __builtin_ctz(a);
|
||||||
|
#else
|
||||||
|
return lfs_npw2((a & -a) + 1) - 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of binary ones in a
|
||||||
|
static inline uint32_t lfs_popc(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||||
|
return __builtin_popcount(a);
|
||||||
|
#else
|
||||||
|
a = a - ((a >> 1) & 0x55555555);
|
||||||
|
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||||
|
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the sequence comparison of a and b, this is the distance
|
||||||
|
// between a and b ignoring overflow
|
||||||
|
static inline int lfs_scmp(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return (int)(unsigned)(a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from 32-bit little-endian to native order
|
||||||
|
static inline uint32_t lfs_fromle32(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && ((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
|
||||||
|
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||||
|
return a;
|
||||||
|
#elif !defined(LFS_NO_INTRINSICS) && \
|
||||||
|
((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
|
return __builtin_bswap32(a);
|
||||||
|
#else
|
||||||
|
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) | (((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to 32-bit little-endian from native order
|
||||||
|
static inline uint32_t lfs_tole32(uint32_t a)
|
||||||
|
{
|
||||||
|
return lfs_fromle32(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||||
|
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
|
||||||
|
|
||||||
|
// Allocate memory, only used if buffers are not provided to littlefs
|
||||||
|
static inline void *lfs_malloc(size_t size)
|
||||||
|
{
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
return malloc(size);
|
||||||
|
#else
|
||||||
|
(void)size;
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||||
|
static inline void lfs_free(void *p)
|
||||||
|
{
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
free(p);
|
||||||
|
#else
|
||||||
|
(void)p;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -32,6 +32,8 @@ void powerCommandsCheck()
|
|||||||
delete screen;
|
delete screen;
|
||||||
LOG_DEBUG("final reboot!");
|
LOG_DEBUG("final reboot!");
|
||||||
reboot();
|
reboot();
|
||||||
|
#elif defined(ARCH_STM32WL)
|
||||||
|
HAL_NVIC_SystemReset();
|
||||||
#else
|
#else
|
||||||
rebootAtMsec = -1;
|
rebootAtMsec = -1;
|
||||||
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
|
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
|
||||||
|
|||||||
@@ -40,5 +40,9 @@
|
|||||||
// "USERPREFS_OEM_IMAGE_WIDTH": "50",
|
// "USERPREFS_OEM_IMAGE_WIDTH": "50",
|
||||||
// "USERPREFS_OEM_IMAGE_HEIGHT": "28",
|
// "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_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 "
|
"USERPREFS_TZ_STRING": "tzplaceholder "
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ extends = stm32_base
|
|||||||
; `ebyte_e77_dev` was added in this commit. Remove when a new release is used in the base.
|
; `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
|
platform = https://github.com/platformio/platform-ststm32.git#3208828db447f4373cd303b7f7393c8fc0dae623
|
||||||
board = ebyte_e77_dev
|
board = ebyte_e77_dev
|
||||||
|
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
|
||||||
board_level = extra
|
board_level = extra
|
||||||
build_flags =
|
build_flags =
|
||||||
${stm32_base.build_flags}
|
${stm32_base.build_flags}
|
||||||
@@ -11,31 +12,19 @@ build_flags =
|
|||||||
-DPIN_SERIAL_RX=PA3
|
-DPIN_SERIAL_RX=PA3
|
||||||
-DPIN_SERIAL_TX=PA2
|
-DPIN_SERIAL_TX=PA2
|
||||||
-DHAL_DAC_MODULE_ONLY
|
-DHAL_DAC_MODULE_ONLY
|
||||||
-DHAL_ADC_MODULE_DISABLED
|
-DHAL_RNG_MODULE_ENABLED
|
||||||
-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
|
|
||||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||||
-DRADIOLIB_EXCLUDE_LR11X0=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
|
upload_port = stlink
|
||||||
12
variants/hackerboxes_esp32_io/platformio.ini
Normal file
12
variants/hackerboxes_esp32_io/platformio.ini
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[env:hackerboxes-esp32-io]
|
||||||
|
extends = esp32_base
|
||||||
|
board = esp32dev
|
||||||
|
board_level = extra
|
||||||
|
build_flags =
|
||||||
|
${esp32_base.build_flags}
|
||||||
|
-D PRIVATE_HW
|
||||||
|
-I variants/hackerboxes_esp32_io
|
||||||
|
monitor_speed = 115200
|
||||||
|
upload_protocol = esptool
|
||||||
|
;upload_port = /dev/ttyUSB0
|
||||||
|
upload_speed = 921600
|
||||||
30
variants/hackerboxes_esp32_io/variant.h
Normal file
30
variants/hackerboxes_esp32_io/variant.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#define BUTTON_PIN 0
|
||||||
|
|
||||||
|
// HACKBOX LoRa IO Kit
|
||||||
|
// Uses a ESP-32-WROOM and a RA-01SH (SX1262) LoRa Board
|
||||||
|
|
||||||
|
#define LED_PIN 2 // LED
|
||||||
|
#define LED_STATE_ON 1 // State when LED is lit
|
||||||
|
|
||||||
|
#define HAS_SCREEN 0
|
||||||
|
#define HAS_GPS 0
|
||||||
|
#undef GPS_RX_PIN
|
||||||
|
#undef GPS_TX_PIN
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
#define LORA_SCK 18
|
||||||
|
#define LORA_MISO 19
|
||||||
|
#define LORA_MOSI 23
|
||||||
|
#define LORA_CS 5
|
||||||
|
#define LORA_DIO0 RADIOLIB_NC
|
||||||
|
#define LORA_RESET 27
|
||||||
|
#define LORA_DIO1 33
|
||||||
|
#define LORA_DIO2 RADIOLIB_NC
|
||||||
|
#define LORA_BUSY 32
|
||||||
|
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 LORA_DIO1
|
||||||
|
#define SX126X_BUSY LORA_BUSY
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_MAX_POWER 22 // Max power of the RA-01SH is 22db
|
||||||
14
variants/hackerboxes_esp32c3_oled/platformio.ini
Normal file
14
variants/hackerboxes_esp32c3_oled/platformio.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[env:hackerboxes-esp32c3-oled]
|
||||||
|
extends = esp32c3_base
|
||||||
|
board = esp32-c3-devkitm-1
|
||||||
|
board_level = extra
|
||||||
|
build_flags =
|
||||||
|
${esp32_base.build_flags}
|
||||||
|
-D PRIVATE_HW
|
||||||
|
-D ARDUINO_USB_MODE=1
|
||||||
|
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
-I variants/hackerboxes_esp32c3_oled
|
||||||
|
monitor_speed = 115200
|
||||||
|
upload_protocol = esptool
|
||||||
|
;upload_port = /dev/ttyUSB0
|
||||||
|
upload_speed = 921600
|
||||||
36
variants/hackerboxes_esp32c3_oled/variant.h
Normal file
36
variants/hackerboxes_esp32c3_oled/variant.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#define BUTTON_PIN 9
|
||||||
|
|
||||||
|
// Hackerboxes LoRa ESP32-C3 OLED Kit
|
||||||
|
// Uses a ESP32-C3 OLED Board and a RA-01SH (SX1262) LoRa Board
|
||||||
|
|
||||||
|
#define LED_PIN 8 // LED
|
||||||
|
#define LED_STATE_ON 1 // State when LED is lit
|
||||||
|
|
||||||
|
#define HAS_SCREEN 0
|
||||||
|
#define HAS_GPS 0
|
||||||
|
#undef GPS_RX_PIN
|
||||||
|
#undef GPS_TX_PIN
|
||||||
|
|
||||||
|
// #define USE_SSD1306_72_40
|
||||||
|
// #define I2C_SDA 5 // I2C pins for this board
|
||||||
|
// #define I2C_SCL 6 //
|
||||||
|
// #define TFT_WIDTH 72
|
||||||
|
// #define TFT_HEIGHT 40
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
#define LORA_SCK 4
|
||||||
|
#define LORA_MISO 7
|
||||||
|
#define LORA_MOSI 3
|
||||||
|
#define LORA_CS 1
|
||||||
|
#define LORA_DIO0 RADIOLIB_NC
|
||||||
|
#define LORA_RESET 0
|
||||||
|
#define LORA_DIO1 20
|
||||||
|
#define LORA_DIO2 RADIOLIB_NC
|
||||||
|
#define LORA_BUSY 10
|
||||||
|
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 LORA_DIO1
|
||||||
|
#define SX126X_BUSY LORA_BUSY
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_MAX_POWER 22 // Max power of the RA-01SH is 22db
|
||||||
11
variants/heltec_sensor_hub/platformio.ini
Normal file
11
variants/heltec_sensor_hub/platformio.ini
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[env:heltec_sensor_hub]
|
||||||
|
extends = esp32s3_base
|
||||||
|
board = heltec_wifi_lora_32_V3
|
||||||
|
board_check = true
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${esp32s3_base.build_flags} -I variants/heltec_sensor_hub
|
||||||
|
-D HELTEC_SENSOR_HUB
|
||||||
|
|
||||||
|
lib_deps = ${esp32s3_base.lib_deps}
|
||||||
|
adafruit/Adafruit NeoPixel @ ^1.12.0
|
||||||
46
variants/heltec_sensor_hub/variant.h
Normal file
46
variants/heltec_sensor_hub/variant.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#define EXT_PWR_DETECT 20
|
||||||
|
|
||||||
|
#define BUTTON_PIN 17
|
||||||
|
|
||||||
|
#define BATTERY_PIN 7 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||||
|
#define ADC_CHANNEL ADC1_GPIO7_CHANNEL
|
||||||
|
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
|
||||||
|
#define ADC_MULTIPLIER (4.9 * 1.045)
|
||||||
|
#define ADC_CTRL 34 // active HIGH, powers the voltage divider. Only on 1.1
|
||||||
|
#define ADC_CTRL_ENABLED HIGH
|
||||||
|
|
||||||
|
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||||
|
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||||
|
#define NEOPIXEL_DATA 18 // gpio pin used to send data to the neopixels
|
||||||
|
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
#define LORA_DIO0 RADIOLIB_NC
|
||||||
|
#define LORA_RESET 12
|
||||||
|
#define LORA_DIO1 14 // SX1262 IRQ
|
||||||
|
#define LORA_DIO2 13 // SX1262 BUSY
|
||||||
|
|
||||||
|
#define LORA_SCK 9
|
||||||
|
#define LORA_MISO 11
|
||||||
|
#define LORA_MOSI 10
|
||||||
|
#define LORA_CS 8
|
||||||
|
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 LORA_DIO1
|
||||||
|
#define SX126X_BUSY LORA_DIO2
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
|
||||||
|
#define I2C_SDA 1
|
||||||
|
#define I2C_SCL 2
|
||||||
|
#define HAS_SCREEN 0
|
||||||
|
#define SENSOR_POWER_CTRL_PIN 33
|
||||||
|
#define SENSOR_POWER_ON 1
|
||||||
|
|
||||||
|
#define PERIPHERAL_WARMUP_MS 100
|
||||||
|
|
||||||
|
#define ESP32S3_WAKE_TYPE ESP_EXT1_WAKEUP_ANY_HIGH
|
||||||
|
|
||||||
|
#define ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE 1
|
||||||
@@ -27,6 +27,7 @@ build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunctio
|
|||||||
-D USE_X11=1
|
-D USE_X11=1
|
||||||
-D HAS_TFT=1
|
-D HAS_TFT=1
|
||||||
-D HAS_SCREEN=0
|
-D HAS_SCREEN=0
|
||||||
|
-D LV_CACHE_DEF_SIZE=6291456
|
||||||
-D LV_BUILD_TEST=0
|
-D LV_BUILD_TEST=0
|
||||||
-D LV_USE_LIBINPUT=1
|
-D LV_USE_LIBINPUT=1
|
||||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
-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 USE_X11=1
|
||||||
-D HAS_TFT=1
|
-D HAS_TFT=1
|
||||||
-D HAS_SCREEN=0
|
-D HAS_SCREEN=0
|
||||||
; -D CALIBRATE_TOUCH=0
|
-D LV_CACHE_DEF_SIZE=6291456
|
||||||
-D LV_BUILD_TEST=0
|
-D LV_BUILD_TEST=0
|
||||||
-D LV_USE_LOG=1
|
-D LV_USE_LOG=1
|
||||||
-D LV_USE_SYSMON=1
|
-D LV_USE_SYSMON=1
|
||||||
|
|||||||
@@ -1,36 +1,23 @@
|
|||||||
[env:rak3172]
|
[env:rak3172]
|
||||||
extends = stm32_base
|
extends = stm32_base
|
||||||
board = wiscore_rak3172
|
board = wiscore_rak3172
|
||||||
|
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
|
||||||
build_flags =
|
build_flags =
|
||||||
${stm32_base.build_flags}
|
${stm32_base.build_flags}
|
||||||
-Ivariants/rak3172
|
-Ivariants/rak3172
|
||||||
-DSERIAL_UART_INSTANCE=1
|
|
||||||
-DPIN_SERIAL_RX=PB7
|
|
||||||
-DPIN_SERIAL_TX=PB6
|
|
||||||
-DHAL_DAC_MODULE_ONLY
|
-DHAL_DAC_MODULE_ONLY
|
||||||
-DHAL_ADC_MODULE_DISABLED
|
-DHAL_RNG_MODULE_ENABLED
|
||||||
-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
|
|
||||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||||
upload_port = stlink
|
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_I2C=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_WIFI=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_BLUETOOTH=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_GPS=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_SCREEN=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_MQTT=1
|
||||||
|
-DMESHTASTIC_EXCLUDE_POWERMON=1
|
||||||
|
;-DPIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
|
||||||
|
;-DCFG_DEBUG
|
||||||
|
upload_port = stlink
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
STM32WLE5 Core Module for LoRaWAN® RAK3372
|
||||||
|
https://store.rakwireless.com/products/wisblock-core-module-rak3372
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This variant is a work in progress.
|
This variant is a work in progress.
|
||||||
Do not expect a working Meshtastic device with this target.
|
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
|
#define USE_STM32WLx
|
||||||
|
|
||||||
#endif
|
#define LED_PIN PA0 // Green LED
|
||||||
|
#define LED_STATE_ON 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ build_flags =
|
|||||||
-D HAS_SCREEN=0
|
-D HAS_SCREEN=0
|
||||||
-D HAS_TFT=1
|
-D HAS_TFT=1
|
||||||
-D USE_I2S_BUZZER
|
-D USE_I2S_BUZZER
|
||||||
-D RAM_SIZE=4096
|
-D RAM_SIZE=5120
|
||||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||||
-D LV_CONF_INCLUDE_SIMPLE
|
-D LV_CONF_INCLUDE_SIMPLE
|
||||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||||
@@ -66,6 +66,7 @@ build_flags =
|
|||||||
-D VIEW_320x240
|
-D VIEW_320x240
|
||||||
; -D USE_DOUBLE_BUFFER
|
; -D USE_DOUBLE_BUFFER
|
||||||
-D USE_PACKET_API
|
-D USE_PACKET_API
|
||||||
|
-D MAP_FULL_REDRAW
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env:t-deck.lib_deps}
|
${env:t-deck.lib_deps}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[env:wio-e5]
|
[env:wio-e5]
|
||||||
extends = stm32_base
|
extends = stm32_base
|
||||||
board = lora_e5_dev_board
|
board = lora_e5_dev_board
|
||||||
|
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
|
||||||
build_flags =
|
build_flags =
|
||||||
${stm32_base.build_flags}
|
${stm32_base.build_flags}
|
||||||
-Ivariants/wio-e5
|
-Ivariants/wio-e5
|
||||||
@@ -8,31 +9,19 @@ build_flags =
|
|||||||
-DPIN_SERIAL_RX=PB7
|
-DPIN_SERIAL_RX=PB7
|
||||||
-DPIN_SERIAL_TX=PB6
|
-DPIN_SERIAL_TX=PB6
|
||||||
-DHAL_DAC_MODULE_ONLY
|
-DHAL_DAC_MODULE_ONLY
|
||||||
-DHAL_ADC_MODULE_DISABLED
|
-DHAL_RNG_MODULE_ENABLED
|
||||||
-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
|
|
||||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||||
-DRADIOLIB_EXCLUDE_LR11X0=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
|
upload_port = stlink
|
||||||
@@ -17,4 +17,9 @@ Do not expect a working Meshtastic device with this target.
|
|||||||
#define LED_PIN PB5
|
#define LED_PIN PB5
|
||||||
#define LED_STATE_ON 1
|
#define LED_STATE_ON 1
|
||||||
|
|
||||||
|
#if (defined(LED_BUILTIN) && LED_BUILTIN == PNUM_NOT_DEFINED)
|
||||||
|
#undef LED_BUILTIN
|
||||||
|
#define LED_BUILTIN (LED_PIN)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[VERSION]
|
[VERSION]
|
||||||
major = 2
|
major = 2
|
||||||
minor = 6
|
minor = 6
|
||||||
build = 2
|
build = 3
|
||||||
|
|||||||
Reference in New Issue
Block a user