diff --git a/Boards/Simulator/Source/LvglTask.cpp b/Boards/Simulator/Source/LvglTask.cpp
index 0d1120d4..ce347f78 100644
--- a/Boards/Simulator/Source/LvglTask.cpp
+++ b/Boards/Simulator/Source/LvglTask.cpp
@@ -82,6 +82,7 @@ static void lvgl_task(TT_UNUSED void* arg) {
* but somehow that doesn't work. Waiting here from a ThreadFlag when that happens
* also doesn't work. It seems that it must be called from this task. */
displayHandle = lv_sdl_window_create(320, 240);
+ lv_sdl_window_set_title(displayHandle, "Tactility");
uint32_t task_delay_ms = task_max_sleep_ms;
diff --git a/Data/config/placeholder.txt b/Data/config/placeholder.txt
deleted file mode 100644
index e69de29b..00000000
diff --git a/Data/data/test.txt b/Data/data/test.txt
new file mode 100644
index 00000000..ead4f5ba
--- /dev/null
+++ b/Data/data/test.txt
@@ -0,0 +1,2 @@
+This file exists to test the partition.
+It can be deleted when the partition contains other files.
diff --git a/Data/assets/boot_logo.png b/Data/system/app/Boot/logo.png
similarity index 100%
rename from Data/assets/boot_logo.png
rename to Data/system/app/Boot/logo.png
diff --git a/Data/assets/boot_logo_usb.png b/Data/system/app/Boot/logo_usb.png
similarity index 100%
rename from Data/assets/boot_logo_usb.png
rename to Data/system/app/Boot/logo_usb.png
diff --git a/Data/assets/desktop_icon_apps.png b/Data/system/app/Desktop/icon_apps.png
similarity index 100%
rename from Data/assets/desktop_icon_apps.png
rename to Data/system/app/Desktop/icon_apps.png
diff --git a/Data/assets/desktop_icon_files.png b/Data/system/app/Desktop/icon_files.png
similarity index 100%
rename from Data/assets/desktop_icon_files.png
rename to Data/system/app/Desktop/icon_files.png
diff --git a/Data/assets/desktop_icon_settings.png b/Data/system/app/Desktop/icon_settings.png
similarity index 100%
rename from Data/assets/desktop_icon_settings.png
rename to Data/system/app/Desktop/icon_settings.png
diff --git a/Data/assets/wifi_lock_black.png b/Data/system/app/WifiManage/lock.png
similarity index 100%
rename from Data/assets/wifi_lock_black.png
rename to Data/system/app/WifiManage/lock.png
diff --git a/Data/assets/wifi_signal_medium_black.png b/Data/system/app/WifiManage/signal_medium.png
similarity index 100%
rename from Data/assets/wifi_signal_medium_black.png
rename to Data/system/app/WifiManage/signal_medium.png
diff --git a/Data/assets/wifi_signal_strong_black.png b/Data/system/app/WifiManage/signal_strong.png
similarity index 100%
rename from Data/assets/wifi_signal_strong_black.png
rename to Data/system/app/WifiManage/signal_strong.png
diff --git a/Data/assets/wifi_signal_weak_black.png b/Data/system/app/WifiManage/signal_weak.png
similarity index 100%
rename from Data/assets/wifi_signal_weak_black.png
rename to Data/system/app/WifiManage/signal_weak.png
diff --git a/Data/assets/app_icon_display_settings.png b/Data/system/app_icon_display_settings.png
similarity index 100%
rename from Data/assets/app_icon_display_settings.png
rename to Data/system/app_icon_display_settings.png
diff --git a/Data/assets/app_icon_fallback.png b/Data/system/app_icon_fallback.png
similarity index 100%
rename from Data/assets/app_icon_fallback.png
rename to Data/system/app_icon_fallback.png
diff --git a/Data/assets/app_icon_files.png b/Data/system/app_icon_files.png
similarity index 100%
rename from Data/assets/app_icon_files.png
rename to Data/system/app_icon_files.png
diff --git a/Data/assets/app_icon_i2c.png b/Data/system/app_icon_i2c.png
similarity index 100%
rename from Data/assets/app_icon_i2c.png
rename to Data/system/app_icon_i2c.png
diff --git a/Data/assets/app_icon_power_settings.png b/Data/system/app_icon_power_settings.png
similarity index 100%
rename from Data/assets/app_icon_power_settings.png
rename to Data/system/app_icon_power_settings.png
diff --git a/Data/assets/app_icon_settings.png b/Data/system/app_icon_settings.png
similarity index 100%
rename from Data/assets/app_icon_settings.png
rename to Data/system/app_icon_settings.png
diff --git a/Data/assets/app_icon_system_info.png b/Data/system/app_icon_system_info.png
similarity index 100%
rename from Data/assets/app_icon_system_info.png
rename to Data/system/app_icon_system_info.png
diff --git a/Data/assets/power_0.png b/Data/system/service/Statusbar/power_0.png
similarity index 100%
rename from Data/assets/power_0.png
rename to Data/system/service/Statusbar/power_0.png
diff --git a/Data/assets/power_10.png b/Data/system/service/Statusbar/power_10.png
similarity index 100%
rename from Data/assets/power_10.png
rename to Data/system/service/Statusbar/power_10.png
diff --git a/Data/assets/power_100.png b/Data/system/service/Statusbar/power_100.png
similarity index 100%
rename from Data/assets/power_100.png
rename to Data/system/service/Statusbar/power_100.png
diff --git a/Data/assets/power_20.png b/Data/system/service/Statusbar/power_20.png
similarity index 100%
rename from Data/assets/power_20.png
rename to Data/system/service/Statusbar/power_20.png
diff --git a/Data/assets/power_30.png b/Data/system/service/Statusbar/power_30.png
similarity index 100%
rename from Data/assets/power_30.png
rename to Data/system/service/Statusbar/power_30.png
diff --git a/Data/assets/power_40.png b/Data/system/service/Statusbar/power_40.png
similarity index 100%
rename from Data/assets/power_40.png
rename to Data/system/service/Statusbar/power_40.png
diff --git a/Data/assets/power_50.png b/Data/system/service/Statusbar/power_50.png
similarity index 100%
rename from Data/assets/power_50.png
rename to Data/system/service/Statusbar/power_50.png
diff --git a/Data/assets/power_60.png b/Data/system/service/Statusbar/power_60.png
similarity index 100%
rename from Data/assets/power_60.png
rename to Data/system/service/Statusbar/power_60.png
diff --git a/Data/assets/power_70.png b/Data/system/service/Statusbar/power_70.png
similarity index 100%
rename from Data/assets/power_70.png
rename to Data/system/service/Statusbar/power_70.png
diff --git a/Data/assets/power_80.png b/Data/system/service/Statusbar/power_80.png
similarity index 100%
rename from Data/assets/power_80.png
rename to Data/system/service/Statusbar/power_80.png
diff --git a/Data/assets/power_90.png b/Data/system/service/Statusbar/power_90.png
similarity index 100%
rename from Data/assets/power_90.png
rename to Data/system/service/Statusbar/power_90.png
diff --git a/Data/assets/sdcard.png b/Data/system/service/Statusbar/sdcard.png
similarity index 100%
rename from Data/assets/sdcard.png
rename to Data/system/service/Statusbar/sdcard.png
diff --git a/Data/assets/sdcard_alert.png b/Data/system/service/Statusbar/sdcard_alert.png
similarity index 100%
rename from Data/assets/sdcard_alert.png
rename to Data/system/service/Statusbar/sdcard_alert.png
diff --git a/Data/assets/wifi_off_white.png b/Data/system/service/Statusbar/wifi_off_white.png
similarity index 100%
rename from Data/assets/wifi_off_white.png
rename to Data/system/service/Statusbar/wifi_off_white.png
diff --git a/Data/assets/wifi_scan_white.png b/Data/system/service/Statusbar/wifi_scan_white.png
similarity index 100%
rename from Data/assets/wifi_scan_white.png
rename to Data/system/service/Statusbar/wifi_scan_white.png
diff --git a/Data/assets/wifi_signal_medium_white.png b/Data/system/service/Statusbar/wifi_signal_medium_white.png
similarity index 100%
rename from Data/assets/wifi_signal_medium_white.png
rename to Data/system/service/Statusbar/wifi_signal_medium_white.png
diff --git a/Data/assets/wifi_signal_strong_white.png b/Data/system/service/Statusbar/wifi_signal_strong_white.png
similarity index 100%
rename from Data/assets/wifi_signal_strong_white.png
rename to Data/system/service/Statusbar/wifi_signal_strong_white.png
diff --git a/Data/assets/wifi_signal_weak_white.png b/Data/system/service/Statusbar/wifi_signal_weak_white.png
similarity index 100%
rename from Data/assets/wifi_signal_weak_white.png
rename to Data/system/service/Statusbar/wifi_signal_weak_white.png
diff --git a/Data/assets/spinner.png b/Data/system/spinner.png
similarity index 100%
rename from Data/assets/spinner.png
rename to Data/system/spinner.png
diff --git a/Data/assets_sources/Desktop Icons.svg b/Data/system_sources/App Icons.svg
similarity index 100%
rename from Data/assets_sources/Desktop Icons.svg
rename to Data/system_sources/App Icons.svg
diff --git a/Data/assets_sources/Statusbar Battery.kra b/Data/system_sources/Statusbar Battery.kra
similarity index 100%
rename from Data/assets_sources/Statusbar Battery.kra
rename to Data/system_sources/Statusbar Battery.kra
diff --git a/Data/assets_sources/Statusbar sdcard.kra b/Data/system_sources/Statusbar sdcard.kra
similarity index 100%
rename from Data/assets_sources/Statusbar sdcard.kra
rename to Data/system_sources/Statusbar sdcard.kra
diff --git a/Data/assets_sources/TactilitySpinner.svg b/Data/system_sources/TactilitySpinner.svg
similarity index 100%
rename from Data/assets_sources/TactilitySpinner.svg
rename to Data/system_sources/TactilitySpinner.svg
diff --git a/Data/assets_sources/boot_logo.svg b/Data/system_sources/app/Boot/logo.svg
similarity index 100%
rename from Data/assets_sources/boot_logo.svg
rename to Data/system_sources/app/Boot/logo.svg
diff --git a/Data/assets_sources/boot_logo_usb.svg b/Data/system_sources/app/Boot/logo_usb.svg
similarity index 100%
rename from Data/assets_sources/boot_logo_usb.svg
rename to Data/system_sources/app/Boot/logo_usb.svg
diff --git a/Data/system_sources/app/Desktop/apps.svg b/Data/system_sources/app/Desktop/apps.svg
new file mode 100644
index 00000000..bb14bc03
--- /dev/null
+++ b/Data/system_sources/app/Desktop/apps.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Data/system_sources/app/Desktop/folder.svg b/Data/system_sources/app/Desktop/folder.svg
new file mode 100644
index 00000000..021db149
--- /dev/null
+++ b/Data/system_sources/app/Desktop/folder.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Data/system_sources/app/Desktop/settings.svg b/Data/system_sources/app/Desktop/settings.svg
new file mode 100644
index 00000000..63cebb1c
--- /dev/null
+++ b/Data/system_sources/app/Desktop/settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Data/assets_sources/wifi_lock_black.svg b/Data/system_sources/app/WifiManage/lock.svg
similarity index 100%
rename from Data/assets_sources/wifi_lock_black.svg
rename to Data/system_sources/app/WifiManage/lock.svg
diff --git a/Data/assets_sources/wifi_signal_medium_black.svg b/Data/system_sources/app/WifiManage/signal_medium.svg
similarity index 100%
rename from Data/assets_sources/wifi_signal_medium_black.svg
rename to Data/system_sources/app/WifiManage/signal_medium.svg
diff --git a/Data/assets_sources/wifi_signal_strong_black.svg b/Data/system_sources/app/WifiManage/signal_strong.svg
similarity index 100%
rename from Data/assets_sources/wifi_signal_strong_black.svg
rename to Data/system_sources/app/WifiManage/signal_strong.svg
diff --git a/Data/assets_sources/wifi_signal_weak_black.svg b/Data/system_sources/app/WifiManage/signal_weak.svg
similarity index 100%
rename from Data/assets_sources/wifi_signal_weak_black.svg
rename to Data/system_sources/app/WifiManage/signal_weak.svg
diff --git a/Data/assets_sources/sdcard.svg b/Data/system_sources/sdcard.svg
similarity index 100%
rename from Data/assets_sources/sdcard.svg
rename to Data/system_sources/sdcard.svg
diff --git a/Data/assets_sources/sdcard_alert.svg b/Data/system_sources/sdcard_alert.svg
similarity index 100%
rename from Data/assets_sources/sdcard_alert.svg
rename to Data/system_sources/sdcard_alert.svg
diff --git a/Data/assets_sources/wifi_off_white.svg b/Data/system_sources/wifi_off_white.svg
similarity index 100%
rename from Data/assets_sources/wifi_off_white.svg
rename to Data/system_sources/wifi_off_white.svg
diff --git a/Data/assets_sources/wifi_scan_white.svg b/Data/system_sources/wifi_scan_white.svg
similarity index 100%
rename from Data/assets_sources/wifi_scan_white.svg
rename to Data/system_sources/wifi_scan_white.svg
diff --git a/Data/assets_sources/wifi_signal_medium_white.svg b/Data/system_sources/wifi_signal_medium_white.svg
similarity index 100%
rename from Data/assets_sources/wifi_signal_medium_white.svg
rename to Data/system_sources/wifi_signal_medium_white.svg
diff --git a/Data/assets_sources/wifi_signal_strong_white.svg b/Data/system_sources/wifi_signal_strong_white.svg
similarity index 100%
rename from Data/assets_sources/wifi_signal_strong_white.svg
rename to Data/system_sources/wifi_signal_strong_white.svg
diff --git a/Data/assets_sources/wifi_signal_weak_white.svg b/Data/system_sources/wifi_signal_weak_white.svg
similarity index 100%
rename from Data/assets_sources/wifi_signal_weak_white.svg
rename to Data/system_sources/wifi_signal_weak_white.svg
diff --git a/Documentation/ideas.md b/Documentation/ideas.md
index 9f4814b7..ab48ed76 100644
--- a/Documentation/ideas.md
+++ b/Documentation/ideas.md
@@ -10,6 +10,7 @@
- Show error in WiFi screen (e.g. AlertDialog when SPI is not enabled and available memory is below a certain amount)
- Clean up static_cast when casting to base class.
- M5Stack CoreS3 SD card mounts, but cannot be read. There is currently a notice about it [here](https://github.com/espressif/esp-bsp/blob/master/bsp/m5stack_core_s3/README.md).
+- SD card statusbar icon shows error when there's a read timeout on the SD card status. Don't show the error icon in this scenario.
# TODOs
- Call tt::lvgl::isSyncSet after HAL init and show error (and crash?) when it is not set.
diff --git a/README.md b/README.md
index f1340359..a48e5712 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Tactility is an operating system that focuses on the ESP32 microcontroller family.
-See [https://tactility.bytewelder.com](https://tactility.bytewelder.com) for more information.
+See [https://tactility.one](https://tactility.one) for more information.
Status: pre-release
diff --git a/Tactility/Private/app/AppInstance.h b/Tactility/Private/app/AppInstance.h
index 520e14e8..e039a8fe 100644
--- a/Tactility/Private/app/AppInstance.h
+++ b/Tactility/Private/app/AppInstance.h
@@ -82,6 +82,9 @@ public:
void setResult(Result result) override;
void setResult(Result result, std::shared_ptr bundle) override;
bool hasResult() const override;
+
+ std::unique_ptr getPaths() const override;
+
std::unique_ptr& getResult() { return resultHolder; }
};
diff --git a/Tactility/Private/app/AppInstancePaths.h b/Tactility/Private/app/AppInstancePaths.h
new file mode 100644
index 00000000..eb1f3bae
--- /dev/null
+++ b/Tactility/Private/app/AppInstancePaths.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "app/AppInstance.h"
+
+namespace tt::app {
+
+class AppInstancePaths final : public Paths {
+
+private:
+
+ const AppManifest& manifest;
+
+public:
+
+ explicit AppInstancePaths(const AppManifest& manifest) : manifest(manifest) {}
+ ~AppInstancePaths() final = default;
+
+ std::string getDataDirectory() const final;
+ std::string getDataDirectoryLvgl() const final;
+ std::string getDataPath(const std::string& childPath) const final;
+ std::string getDataPathLvgl(const std::string& childPath) const final;
+ std::string getSystemDirectory() const final;
+ std::string getSystemDirectoryLvgl() const final;
+ std::string getSystemPath(const std::string& childPath) const final;
+ std::string getSystemPathLvgl(const std::string& childPath) const final;
+};
+
+}
\ No newline at end of file
diff --git a/Tactility/Source/app/AppContext.h b/Tactility/Source/app/AppContext.h
index 4b82340c..238017ad 100644
--- a/Tactility/Source/app/AppContext.h
+++ b/Tactility/Source/app/AppContext.h
@@ -6,6 +6,8 @@
namespace tt::app {
+class Paths;
+
typedef union {
struct {
bool showStatusbar : 1;
@@ -33,6 +35,68 @@ public:
virtual void setResult(Result result) = 0;
virtual void setResult(Result result, std::shared_ptr bundle)= 0;
virtual bool hasResult() const = 0;
+ virtual std::unique_ptr getPaths() const = 0;
+};
+
+class Paths {
+
+public:
+
+ Paths() = default;
+ virtual ~Paths() = default;
+
+ /**
+ * Returns the directory path for the data location for an app.
+ * The data directory is intended to survive OS upgrades.
+ * The path will not end with a "/".
+ */
+ virtual std::string getDataDirectory() const = 0;
+
+ /**
+ * @see getDataDirectory(), but with LVGL prefix.
+ */
+ virtual std::string getDataDirectoryLvgl() const = 0;
+
+ /**
+ * Returns the full path for an entry inside the data location for an app.
+ * The data directory is intended to survive OS upgrades.
+ * Configuration data should be stored here.
+ * @param[in] childPath the path without a "/" prefix
+ */
+ virtual std::string getDataPath(const std::string& childPath) const = 0;
+
+ /**
+ * @see getDataPath(), but with LVGL prefix.
+ */
+ virtual std::string getDataPathLvgl(const std::string& childPath) const = 0;
+
+ /**
+ * Returns the directory path for the system location for an app.
+ * The system directory is not intended to survive OS upgrades.
+ * You should not store configuration data here.
+ * The path will not end with a "/".
+ * This is mainly used for core apps (system/boot/settings type).
+ */
+ virtual std::string getSystemDirectory() const = 0;
+
+ /**
+ * @see getSystemDirectory(), but with LVGL prefix.
+ */
+ virtual std::string getSystemDirectoryLvgl() const = 0;
+
+ /**
+ * Returns the full path for an entry inside the system location for an app.
+ * The data directory is not intended to survive OS upgrades.
+ * You should not store configuration data here.
+ * This is mainly used for core apps (system/boot/settings type).
+ * @param[in] childPath the path without a "/" prefix
+ */
+ virtual std::string getSystemPath(const std::string& childPath) const = 0;
+
+ /**
+ * @see getSystemPath(), but with LVGL prefix.
+ */
+ virtual std::string getSystemPathLvgl(const std::string& childPath) const = 0;
};
}
diff --git a/Tactility/Source/app/AppInstance.cpp b/Tactility/Source/app/AppInstance.cpp
index 86296969..fc07a7a9 100644
--- a/Tactility/Source/app/AppInstance.cpp
+++ b/Tactility/Source/app/AppInstance.cpp
@@ -1,4 +1,5 @@
#include "app/AppInstance.h"
+#include "app/AppInstancePaths.h"
namespace tt::app {
@@ -81,4 +82,8 @@ bool AppInstance::hasResult() const {
return has_result;
}
+std::unique_ptr AppInstance::getPaths() const {
+ return std::make_unique(manifest);
+}
+
} // namespace
diff --git a/Tactility/Source/app/AppInstancePaths.cpp b/Tactility/Source/app/AppInstancePaths.cpp
new file mode 100644
index 00000000..56ae4bb9
--- /dev/null
+++ b/Tactility/Source/app/AppInstancePaths.cpp
@@ -0,0 +1,48 @@
+#include "app/AppInstancePaths.h"
+#include "Partitions.h"
+
+#define LVGL_PATH_PREFIX std::string("A:/")
+#ifdef ESP_PLATFORM
+#define PARTITION_PREFIX std::string("/")
+#else
+#define PARTITION_PREFIX std::string("")
+#endif
+
+namespace tt::app {
+
+std::string AppInstancePaths::getDataDirectory() const {
+ return PARTITION_PREFIX + DATA_PARTITION_NAME + "/app/" + manifest.id;
+}
+
+std::string AppInstancePaths::getDataDirectoryLvgl() const {
+ return LVGL_PATH_PREFIX + DATA_PARTITION_NAME + "/app/" + manifest.id;
+}
+
+std::string AppInstancePaths::getDataPath(const std::string& childPath) const {
+ assert(!childPath.starts_with('/'));
+ return PARTITION_PREFIX + DATA_PARTITION_NAME + "/app/" + manifest.id + '/' + childPath;
+}
+
+std::string AppInstancePaths::getDataPathLvgl(const std::string& childPath) const {
+ assert(!childPath.starts_with('/'));
+ return LVGL_PATH_PREFIX + DATA_PARTITION_NAME + "/app/" + manifest.id + '/' + childPath;
+}
+
+std::string AppInstancePaths::getSystemDirectory() const {
+ return PARTITION_PREFIX + SYSTEM_PARTITION_NAME + "/app/" + manifest.id;
+}
+
+std::string AppInstancePaths::getSystemDirectoryLvgl() const {
+ return LVGL_PATH_PREFIX + SYSTEM_PARTITION_NAME + "/app/" + manifest.id;
+}
+
+std::string AppInstancePaths::getSystemPath(const std::string& childPath) const {
+ assert(!childPath.starts_with('/'));
+ return PARTITION_PREFIX + SYSTEM_PARTITION_NAME + "/app/" + manifest.id + '/' + childPath;
+}
+
+std::string AppInstancePaths::getSystemPathLvgl(const std::string& childPath) const {
+ return LVGL_PATH_PREFIX + SYSTEM_PARTITION_NAME + "/app/" + manifest.id + '/' + childPath;
+}
+
+}
diff --git a/Tactility/Source/app/boot/Boot.cpp b/Tactility/Source/app/boot/Boot.cpp
index 1aaf8c43..a48ba056 100644
--- a/Tactility/Source/app/boot/Boot.cpp
+++ b/Tactility/Source/app/boot/Boot.cpp
@@ -18,7 +18,7 @@
#define CONFIG_TT_SPLASH_DURATION 0
#endif
-#define TAG "Boot"
+#define TAG "boot"
namespace tt::app::boot {
@@ -90,11 +90,11 @@ static void onShow(TT_UNUSED AppContext& app, lv_obj_t* parent) {
lv_obj_t* image = lv_image_create(parent);
lv_obj_set_size(image, LV_PCT(100), LV_PCT(100));
- if (hal::usb::isUsbBootMode()) {
- lv_image_set_src(image, TT_ASSETS_BOOT_LOGO_USB);
- } else {
- lv_image_set_src(image, TT_ASSETS_BOOT_LOGO);
- }
+ auto paths = app.getPaths();
+ const char* logo = hal::usb::isUsbBootMode() ? "logo_usb.png" : "logo.png";
+ auto logo_path = paths->getSystemPathLvgl(logo);
+ TT_LOG_I(TAG, "%s", logo_path.c_str());
+ lv_image_set_src(image, logo_path.c_str());
lvgl::obj_set_style_bg_blacken(parent);
diff --git a/Tactility/Source/app/crashdiagnostics/QrUrl.cpp b/Tactility/Source/app/crashdiagnostics/QrUrl.cpp
index 5c748adf..b2137928 100644
--- a/Tactility/Source/app/crashdiagnostics/QrUrl.cpp
+++ b/Tactility/Source/app/crashdiagnostics/QrUrl.cpp
@@ -25,9 +25,8 @@ std::string getUrlFromCrashData() {
std::stringstream stream;
- stream << "https://oops.bytewelder.com?";
- stream << "i=1"; // Application id
- stream << "&v=" << TT_VERSION; // Version
+ stream << "https://oops.tactility.one";
+ stream << "?v=" << TT_VERSION; // Version
stream << "&a=" << CONFIG_IDF_TARGET; // Architecture
stream << "&s="; // Stacktrace
diff --git a/Tactility/Source/app/desktop/Desktop.cpp b/Tactility/Source/app/desktop/Desktop.cpp
index ac0decdb..8ca12a4e 100644
--- a/Tactility/Source/app/desktop/Desktop.cpp
+++ b/Tactility/Source/app/desktop/Desktop.cpp
@@ -1,7 +1,9 @@
+#include "app/AppContext.h"
#include "app/ManifestRegistry.h"
#include "Check.h"
#include "lvgl.h"
#include "service/loader/Loader.h"
+#include "Assets.h"
namespace tt::app::desktop {
@@ -61,9 +63,13 @@ static void onShow(TT_UNUSED AppContext& app, lv_obj_t* parent) {
int32_t available_width = lv_display_get_horizontal_resolution(display) - (3 * 80);
int32_t padding = TT_MIN(available_width / 4, 64);
- createAppButton(wrapper, "Apps", "A:/assets/desktop_icon_apps.png", "AppList", 0);
- createAppButton(wrapper, "Files", "A:/assets/desktop_icon_files.png", "Files", padding);
- createAppButton(wrapper, "Settings", "A:/assets/desktop_icon_settings.png", "Settings", padding);
+ auto paths = app.getPaths();
+ auto apps_icon_path = paths->getSystemPathLvgl("icon_apps.png");
+ auto files_icon_path = paths->getSystemPathLvgl("icon_files.png");
+ auto settings_icon_path = paths->getSystemPathLvgl("icon_settings.png");
+ createAppButton(wrapper, "Apps", apps_icon_path.c_str(), "AppList", 0);
+ createAppButton(wrapper, "Files", files_icon_path.c_str(), "Files", padding);
+ createAppButton(wrapper, "Settings", settings_icon_path.c_str(), "Settings", padding);
}
extern const AppManifest manifest = {
diff --git a/Tactility/Source/app/files/FileUtils.cpp b/Tactility/Source/app/files/FileUtils.cpp
index 7937d0ca..648323c0 100644
--- a/Tactility/Source/app/files/FileUtils.cpp
+++ b/Tactility/Source/app/files/FileUtils.cpp
@@ -36,6 +36,7 @@ int scandir(
ScandirFilter _Nullable filterMethod,
ScandirSort _Nullable sortMethod
) {
+ TT_LOG_I(TAG, "scandir start");
DIR* dir = opendir(path.c_str());
if (dir == nullptr) {
TT_LOG_E(TAG, "Failed to open dir %s", path.c_str());
@@ -55,6 +56,7 @@ int scandir(
sort(outList.begin(), outList.end(), sortMethod);
}
+ TT_LOG_I(TAG, "scandir finish");
return (int)outList.size();
};
diff --git a/Tactility/Source/app/files/State.cpp b/Tactility/Source/app/files/State.cpp
index 2ff288cf..ed0f0601 100644
--- a/Tactility/Source/app/files/State.cpp
+++ b/Tactility/Source/app/files/State.cpp
@@ -2,6 +2,8 @@
#include "kernel/Kernel.h"
#include "Log.h"
#include "FileUtils.h"
+#include "Partitions.h"
+#include "hal/SdCard.h"
#include
@@ -51,17 +53,17 @@ bool State::setEntriesForPath(const std::string& path) {
dir_entries.push_back({
.d_ino = 0,
.d_type = TT_DT_DIR,
- .d_name = "assets"
+ .d_name = SYSTEM_PARTITION_NAME
});
dir_entries.push_back({
.d_ino = 1,
.d_type = TT_DT_DIR,
- .d_name = "config"
+ .d_name = DATA_PARTITION_NAME
});
dir_entries.push_back({
.d_ino = 2,
.d_type = TT_DT_DIR,
- .d_name = "sdcard"
+ .d_name = TT_SDCARD_MOUNT_NAME
});
current_path = path;
diff --git a/Tactility/Source/app/textviewer/TextViewer.cpp b/Tactility/Source/app/textviewer/TextViewer.cpp
index 4c8e5801..c0b2e006 100644
--- a/Tactility/Source/app/textviewer/TextViewer.cpp
+++ b/Tactility/Source/app/textviewer/TextViewer.cpp
@@ -24,11 +24,16 @@ static void onShow(AppContext& app, lv_obj_t* parent) {
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
auto parameters = app.getParameters();
tt_check(parameters != nullptr, "Parameters missing");
+ bool success = false;
std::string file_argument;
if (parameters->optString(TEXT_VIEWER_FILE_ARGUMENT, file_argument)) {
TT_LOG_I(TAG, "Opening %s", file_argument.c_str());
- lvgl::label_set_text_file(label, file_argument.c_str());
- } else {
+ if (lvgl::label_set_text_file(label, file_argument.c_str())) {
+ success = true;
+ }
+ }
+
+ if (!success) {
lv_label_set_text_fmt(label, "Failed to load %s", file_argument.c_str());
}
}
diff --git a/Tactility/Source/app/wifimanage/View.cpp b/Tactility/Source/app/wifimanage/View.cpp
index e12deb0c..827614dd 100644
--- a/Tactility/Source/app/wifimanage/View.cpp
+++ b/Tactility/Source/app/wifimanage/View.cpp
@@ -2,7 +2,6 @@
#include "WifiManage.h"
#include "Log.h"
-#include "Assets.h"
#include "service/wifi/Wifi.h"
#include "lvgl/Style.h"
#include "lvgl/Toolbar.h"
@@ -19,11 +18,11 @@ std::shared_ptr _Nullable optWifiManage();
const char* getWifiStatusIconForRssi(int rssi) {
if (rssi >= -60) {
- return TT_ASSETS_ICON_WIFI_SIGNAL_STRONG_BLACK;
+ return "signal_strong.png";
} else if (rssi >= -70) {
- return TT_ASSETS_ICON_WIFI_SIGNAL_MEDIUM_BLACK;
+ return "signal_medium.png";
} else {
- return TT_ASSETS_ICON_WIFI_SIGNAL_WEAK_BLACK;
+ return "signal_weak.png";
}
}
@@ -111,13 +110,15 @@ void View::createSsidListItem(const service::wifi::WifiApRecord& record, bool is
lv_obj_align_to(connecting_spinner, info_wrapper, LV_ALIGN_OUT_LEFT_MID, -8, 0);
} else {
const char* icon = getWifiStatusIconForRssi(record.rssi);
+ auto icon_path = paths->getSystemPathLvgl(icon);
lv_obj_t* rssi_image = lv_image_create(wrapper);
- lv_image_set_src(rssi_image, icon);
+ lv_image_set_src(rssi_image, icon_path.c_str());
lv_obj_align(rssi_image, LV_ALIGN_RIGHT_MID, -42, 0);
if (record.auth_mode != WIFI_AUTH_OPEN) {
lv_obj_t* lock_image = lv_image_create(wrapper);
- lv_image_set_src(lock_image, TT_ASSETS_ICON_WIFI_LOCK_BLACK);
+ auto lock = paths->getSystemPathLvgl("lock.png");
+ lv_image_set_src(lock_image, lock.c_str());
lv_obj_align(lock_image, LV_ALIGN_RIGHT_MID, -62, 0);
}
}
@@ -232,6 +233,8 @@ void View::updateEnableOnBootToggle() {
void View::init(const AppContext& app, lv_obj_t* parent) {
root = parent;
+ paths = std::move(app.getPaths());
+
// Toolbar
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_t* toolbar = lvgl::toolbar_create(parent, app);
diff --git a/Tactility/Source/app/wifimanage/View.h b/Tactility/Source/app/wifimanage/View.h
index 1a52db23..bc436bfa 100644
--- a/Tactility/Source/app/wifimanage/View.h
+++ b/Tactility/Source/app/wifimanage/View.h
@@ -13,6 +13,7 @@ private:
Bindings* bindings;
State* state;
+ std::unique_ptr paths;
lv_obj_t* root = nullptr;
lv_obj_t* enable_switch = nullptr;
lv_obj_t* enable_on_boot_switch = nullptr;
diff --git a/Tactility/Source/lvgl/LabelUtils.cpp b/Tactility/Source/lvgl/LabelUtils.cpp
index f56247c0..710f83ad 100644
--- a/Tactility/Source/lvgl/LabelUtils.cpp
+++ b/Tactility/Source/lvgl/LabelUtils.cpp
@@ -5,9 +5,14 @@ namespace tt::lvgl {
#define TAG "tt_lv_label"
-void label_set_text_file(lv_obj_t* label, const char* filepath) {
+bool label_set_text_file(lv_obj_t* label, const char* filepath) {
auto text = file::readString(filepath);
- lv_label_set_text(label, (const char*)text.get());
+ if (text != nullptr) {
+ lv_label_set_text(label, (const char*)text.get());
+ return true;
+ } else {
+ return false;
+ }
}
} // namespace
diff --git a/Tactility/Source/lvgl/LabelUtils.h b/Tactility/Source/lvgl/LabelUtils.h
index e4500231..04cc892f 100644
--- a/Tactility/Source/lvgl/LabelUtils.h
+++ b/Tactility/Source/lvgl/LabelUtils.h
@@ -4,6 +4,6 @@
namespace tt::lvgl {
-void label_set_text_file(lv_obj_t* label, const char* filepath);
+bool label_set_text_file(lv_obj_t* label, const char* filepath);
} // namespace
diff --git a/Tactility/Source/lvgl/Spacer.cpp b/Tactility/Source/lvgl/Spacer.cpp
deleted file mode 100644
index ead7b476..00000000
--- a/Tactility/Source/lvgl/Spacer.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "Spacer.h"
-#include "Style.h"
-
-namespace tt::lvgl {
-
-lv_obj_t* spacer_create(lv_obj_t* parent, int32_t width, int32_t height) {
- lv_obj_t* spacer = lv_obj_create(parent);
- lv_obj_set_size(spacer, width, height);
- obj_set_style_bg_invisible(spacer);
- return spacer;
-}
-
-} // namespace
diff --git a/Tactility/Source/lvgl/Spacer.h b/Tactility/Source/lvgl/Spacer.h
deleted file mode 100644
index 8077c36d..00000000
--- a/Tactility/Source/lvgl/Spacer.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-#include "lvgl.h"
-
-namespace tt::lvgl {
-
-[[deprecated("Use margin")]]
-lv_obj_t* spacer_create(lv_obj_t* parent, int32_t width, int32_t height);
-
-} // namespace
diff --git a/Tactility/Source/lvgl/Statusbar.cpp b/Tactility/Source/lvgl/Statusbar.cpp
index a258d1e1..b9f0bd96 100644
--- a/Tactility/Source/lvgl/Statusbar.cpp
+++ b/Tactility/Source/lvgl/Statusbar.cpp
@@ -4,7 +4,6 @@
#include "Mutex.h"
#include "Pubsub.h"
#include "TactilityCore.h"
-#include "lvgl/Spacer.h"
#include "lvgl/Style.h"
#include "LvglSync.h"
@@ -15,7 +14,7 @@ namespace tt::lvgl {
#define TAG "statusbar"
struct StatusbarIcon {
- const char* image = nullptr;
+ std::string image;
bool visible = false;
bool claimed = false;
};
@@ -89,8 +88,8 @@ static void statusbar_destructor(TT_UNUSED const lv_obj_class_t* class_p, lv_obj
}
static void update_icon(lv_obj_t* image, const StatusbarIcon* icon) {
- if (icon->image != nullptr && icon->visible && icon->claimed) {
- lv_image_set_src(image, icon->image);
+ if (!icon->image.empty() && icon->visible && icon->claimed) {
+ lv_image_set_src(image, icon->image.c_str());
lv_obj_remove_flag(image, LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_add_flag(image, LV_OBJ_FLAG_HIDDEN);
@@ -110,7 +109,9 @@ lv_obj_t* statusbar_create(lv_obj_t* parent) {
lv_obj_center(obj);
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW);
- lv_obj_t* left_spacer = spacer_create(obj, 1, 1);
+ lv_obj_t* left_spacer = lv_obj_create(obj);
+ lv_obj_set_size(left_spacer, 1, 1);
+ obj_set_style_bg_invisible(left_spacer);
lv_obj_set_flex_grow(left_spacer, 1);
statusbar_lock(TtWaitForever);
@@ -154,13 +155,13 @@ static void statusbar_event(TT_UNUSED const lv_obj_class_t* class_p, lv_event_t*
}
}
-int8_t statusbar_icon_add(const char* _Nullable image) {
+int8_t statusbar_icon_add(const std::string& image) {
statusbar_lock(TtWaitForever);
int8_t result = -1;
for (int8_t i = 0; i < STATUSBAR_ICON_LIMIT; ++i) {
if (!statusbar_data.icons[i].claimed) {
statusbar_data.icons[i].claimed = true;
- statusbar_data.icons[i].visible = (image != nullptr);
+ statusbar_data.icons[i].visible = !image.empty();
statusbar_data.icons[i].image = image;
result = i;
TT_LOG_I(TAG, "id %d: added", i);
@@ -172,6 +173,10 @@ int8_t statusbar_icon_add(const char* _Nullable image) {
return result;
}
+int8_t statusbar_icon_add() {
+ return statusbar_icon_add("");
+}
+
void statusbar_icon_remove(int8_t id) {
TT_LOG_I(TAG, "id %d: remove", id);
tt_check(id >= 0 && id < STATUSBAR_ICON_LIMIT);
@@ -179,13 +184,13 @@ void statusbar_icon_remove(int8_t id) {
StatusbarIcon* icon = &statusbar_data.icons[id];
icon->claimed = false;
icon->visible = false;
- icon->image = nullptr;
+ icon->image = "";
tt_pubsub_publish(statusbar_data.pubsub, nullptr);
statusbar_unlock();
}
-void statusbar_icon_set_image(int8_t id, const char* image) {
- TT_LOG_I(TAG, "id %d: set image %s", id, image ? image : "(none)");
+void statusbar_icon_set_image(int8_t id, const std::string& image) {
+ TT_LOG_I(TAG, "id %d: set image %s", id, image.empty() ? "(none)" : image.c_str());
tt_check(id >= 0 && id < STATUSBAR_ICON_LIMIT);
if (statusbar_lock(50 / portTICK_PERIOD_MS)) {
StatusbarIcon* icon = &statusbar_data.icons[id];
diff --git a/Tactility/Source/lvgl/Statusbar.h b/Tactility/Source/lvgl/Statusbar.h
index 56a9f787..9fe71a9d 100644
--- a/Tactility/Source/lvgl/Statusbar.h
+++ b/Tactility/Source/lvgl/Statusbar.h
@@ -10,9 +10,10 @@ namespace tt::lvgl {
#define STATUSBAR_HEIGHT (STATUSBAR_ICON_SIZE + 4) // 4 extra pixels for border and outline
lv_obj_t* statusbar_create(lv_obj_t* parent);
-int8_t statusbar_icon_add(const char* _Nullable image);
+int8_t statusbar_icon_add(const std::string& image);
+int8_t statusbar_icon_add();
void statusbar_icon_remove(int8_t id);
-void statusbar_icon_set_image(int8_t id, const char* image);
+void statusbar_icon_set_image(int8_t id, const std::string& image);
void statusbar_icon_set_visibility(int8_t id, bool visible);
} // namespace
diff --git a/Tactility/Source/lvgl/Toolbar.cpp b/Tactility/Source/lvgl/Toolbar.cpp
index cfa50312..91ffa3ec 100644
--- a/Tactility/Source/lvgl/Toolbar.cpp
+++ b/Tactility/Source/lvgl/Toolbar.cpp
@@ -3,7 +3,6 @@
#include "Toolbar.h"
#include "service/loader/Loader.h"
-#include "lvgl/Spacer.h"
#include "lvgl/Style.h"
#include "Spinner.h"
diff --git a/Tactility/Source/lvgl/Toolbar.h b/Tactility/Source/lvgl/Toolbar.h
index 07a5db3c..2b01bdb5 100644
--- a/Tactility/Source/lvgl/Toolbar.h
+++ b/Tactility/Source/lvgl/Toolbar.h
@@ -16,4 +16,5 @@ void toolbar_set_nav_action(lv_obj_t* obj, const char* icon, lv_event_cb_t callb
lv_obj_t* toolbar_add_button_action(lv_obj_t* obj, const char* icon, lv_event_cb_t callback, void* user_data);
lv_obj_t* toolbar_add_switch_action(lv_obj_t* obj);
lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj);
+
} // namespace
diff --git a/Tactility/Source/service/loader/Loader.cpp b/Tactility/Source/service/loader/Loader.cpp
index bc8f6c9f..56eaf272 100644
--- a/Tactility/Source/service/loader/Loader.cpp
+++ b/Tactility/Source/service/loader/Loader.cpp
@@ -243,7 +243,7 @@ static void stopAppInternal() {
return;
}
- std::unique_ptr result_holder = std::move(app_to_stop->getResult());
+ auto result_holder = std::move(app_to_stop->getResult());
const app::AppManifest& manifest = app_to_stop->getManifest();
transitionAppToState(*app_to_stop, app::StateHiding);
diff --git a/Tactility/Source/service/statusbar/Statusbar.cpp b/Tactility/Source/service/statusbar/Statusbar.cpp
index 8c5397e8..0ac2085b 100644
--- a/Tactility/Source/service/statusbar/Statusbar.cpp
+++ b/Tactility/Source/service/statusbar/Statusbar.cpp
@@ -1,4 +1,3 @@
-#include "Assets.h"
#include "Mutex.h"
#include "Timer.h"
#include "Tactility.h"
@@ -16,18 +15,44 @@ namespace tt::service::statusbar {
#define TAG "statusbar_service"
+// SD card status
+#define STATUSBAR_ICON_SDCARD "sdcard.png"
+#define STATUSBAR_ICON_SDCARD_ALERT "sdcard_alert.png"
+
+// Wifi status
+#define STATUSBAR_ICON_WIFI_OFF_WHITE "wifi_off_white.png"
+#define STATUSBAR_ICON_WIFI_SCAN_WHITE "wifi_scan_white.png"
+#define STATUSBAR_ICON_WIFI_SIGNAL_WEAK_WHITE "wifi_signal_weak_white.png"
+#define STATUSBAR_ICON_WIFI_SIGNAL_MEDIUM_WHITE "wifi_signal_medium_white.png"
+#define STATUSBAR_ICON_WIFI_SIGNAL_STRONG_WHITE "wifi_signal_strong_white.png"
+
+// Power status
+#define STATUSBAR_ICON_POWER_0 "power_0.png"
+#define STATUSBAR_ICON_POWER_10 "power_10.png"
+#define STATUSBAR_ICON_POWER_20 "power_20.png"
+#define STATUSBAR_ICON_POWER_30 "power_30.png"
+#define STATUSBAR_ICON_POWER_40 "power_40.png"
+#define STATUSBAR_ICON_POWER_50 "power_50.png"
+#define STATUSBAR_ICON_POWER_60 "power_60.png"
+#define STATUSBAR_ICON_POWER_70 "power_70.png"
+#define STATUSBAR_ICON_POWER_80 "power_80.png"
+#define STATUSBAR_ICON_POWER_90 "power_90.png"
+#define STATUSBAR_ICON_POWER_100 "power_100.png"
+
extern const ServiceManifest manifest;
struct ServiceData {
Mutex mutex;
std::unique_ptr updateTimer;
- int8_t wifi_icon_id = lvgl::statusbar_icon_add(nullptr);
+ int8_t wifi_icon_id = lvgl::statusbar_icon_add();
const char* wifi_last_icon = nullptr;
- int8_t sdcard_icon_id = lvgl::statusbar_icon_add(nullptr);
+ int8_t sdcard_icon_id = lvgl::statusbar_icon_add();
const char* sdcard_last_icon = nullptr;
- int8_t power_icon_id = lvgl::statusbar_icon_add(nullptr);
+ int8_t power_icon_id = lvgl::statusbar_icon_add();
const char* power_last_icon = nullptr;
+ std::unique_ptr paths;
+
~ServiceData() {
lvgl::statusbar_icon_remove(wifi_icon_id);
lvgl::statusbar_icon_remove(sdcard_icon_id);
@@ -47,24 +72,24 @@ struct ServiceData {
const char* getWifiStatusIconForRssi(int rssi) {
if (rssi >= -60) {
- return TT_ASSETS_ICON_WIFI_SIGNAL_STRONG_WHITE;
+ return STATUSBAR_ICON_WIFI_SIGNAL_STRONG_WHITE;
} else if (rssi >= -70) {
- return TT_ASSETS_ICON_WIFI_SIGNAL_MEDIUM_WHITE;
+ return STATUSBAR_ICON_WIFI_SIGNAL_MEDIUM_WHITE;
} else {
- return TT_ASSETS_ICON_WIFI_SIGNAL_WEAK_WHITE;
+ return STATUSBAR_ICON_WIFI_SIGNAL_WEAK_WHITE;
}
}
-static const char* wifi_get_status_icon(wifi::WifiRadioState state, bool secure) {
+static const char* getWifiStatusIcon(wifi::WifiRadioState state, bool secure) {
int rssi;
switch (state) {
case wifi::WIFI_RADIO_ON:
case wifi::WIFI_RADIO_ON_PENDING:
case wifi::WIFI_RADIO_CONNECTION_PENDING:
- return TT_ASSETS_ICON_WIFI_SCAN_WHITE;
+ return STATUSBAR_ICON_WIFI_SCAN_WHITE;
case wifi::WIFI_RADIO_OFF_PENDING:
case wifi::WIFI_RADIO_OFF:
- return TT_ASSETS_ICON_WIFI_OFF_WHITE;
+ return STATUSBAR_ICON_WIFI_OFF_WHITE;
case wifi::WIFI_RADIO_CONNECTION_ACTIVE:
rssi = wifi::getRssi();
return getWifiStatusIconForRssi(rssi);
@@ -73,12 +98,18 @@ static const char* wifi_get_status_icon(wifi::WifiRadioState state, bool secure)
}
}
-static void update_wifi_icon(std::shared_ptr data) {
+static void updateWifiIcon(const service::Paths* paths, const std::shared_ptr& data) {
wifi::WifiRadioState radio_state = wifi::getRadioState();
bool is_secure = wifi::isConnectionSecure();
- const char* desired_icon = wifi_get_status_icon(radio_state, is_secure);
+ const char* desired_icon = getWifiStatusIcon(radio_state, is_secure);
if (data->wifi_last_icon != desired_icon) {
- lvgl::statusbar_icon_set_image(data->wifi_icon_id, desired_icon);
+ if (desired_icon != nullptr) {
+ auto icon_path = paths->getSystemPathLvgl(desired_icon);
+ lvgl::statusbar_icon_set_image(data->wifi_icon_id, icon_path);
+ lvgl::statusbar_icon_set_visibility(data->wifi_icon_id, true);
+ } else {
+ lvgl::statusbar_icon_set_visibility(data->wifi_icon_id, false);
+ }
data->wifi_last_icon = desired_icon;
}
}
@@ -87,27 +118,32 @@ static void update_wifi_icon(std::shared_ptr data) {
// region sdcard
-static const char* sdcard_get_status_icon(hal::SdCard::State state) {
+static const char* getSdCardStatusIcon(hal::SdCard::State state) {
switch (state) {
case hal::SdCard::StateMounted:
- return TT_ASSETS_ICON_SDCARD;
+ return STATUSBAR_ICON_SDCARD;
case hal::SdCard::StateError:
case hal::SdCard::StateUnmounted:
case hal::SdCard::StateUnknown:
- return TT_ASSETS_ICON_SDCARD_ALERT;
+ return STATUSBAR_ICON_SDCARD_ALERT;
default:
tt_crash("Unhandled SdCard state");
}
}
-static void update_sdcard_icon(std::shared_ptr data) {
+static void updateSdCardIcon(const service::Paths* paths, const std::shared_ptr& data) {
auto sdcard = tt::hal::getConfiguration().sdcard;
if (sdcard != nullptr) {
auto state = sdcard->getState();
- const char* desired_icon = sdcard_get_status_icon(state);
+ const char* desired_icon = getSdCardStatusIcon(state);
if (data->sdcard_last_icon != desired_icon) {
- lvgl::statusbar_icon_set_image(data->sdcard_icon_id, desired_icon);
- lvgl::statusbar_icon_set_visibility(data->sdcard_icon_id, desired_icon != nullptr);
+ if (desired_icon != nullptr) {
+ auto icon_path = paths->getSystemPathLvgl(desired_icon);
+ lvgl::statusbar_icon_set_image(data->sdcard_icon_id, icon_path);
+ lvgl::statusbar_icon_set_visibility(data->sdcard_icon_id, true);
+ } else {
+ lvgl::statusbar_icon_set_visibility(data->sdcard_icon_id, false);
+ }
data->sdcard_last_icon = desired_icon;
}
}
@@ -117,7 +153,7 @@ static void update_sdcard_icon(std::shared_ptr data) {
// region power
-static _Nullable const char* power_get_status_icon() {
+static _Nullable const char* getPowerStatusIcon() {
auto get_power = getConfiguration()->hardware->power;
if (get_power == nullptr) {
return nullptr;
@@ -133,35 +169,40 @@ static _Nullable const char* power_get_status_icon() {
uint8_t charge = charge_level.valueAsUint8;
if (charge >= 95) {
- return TT_ASSETS_ICON_POWER_100;
+ return STATUSBAR_ICON_POWER_100;
} else if (charge >= 85) {
- return TT_ASSETS_ICON_POWER_90;
+ return STATUSBAR_ICON_POWER_90;
} else if (charge >= 75) {
- return TT_ASSETS_ICON_POWER_80;
+ return STATUSBAR_ICON_POWER_80;
} else if (charge >= 65) {
- return TT_ASSETS_ICON_POWER_70;
+ return STATUSBAR_ICON_POWER_70;
} else if (charge >= 55) {
- return TT_ASSETS_ICON_POWER_60;
+ return STATUSBAR_ICON_POWER_60;
} else if (charge >= 45) {
- return TT_ASSETS_ICON_POWER_50;
+ return STATUSBAR_ICON_POWER_50;
} else if (charge >= 35) {
- return TT_ASSETS_ICON_POWER_40;
+ return STATUSBAR_ICON_POWER_40;
} else if (charge >= 25) {
- return TT_ASSETS_ICON_POWER_30;
+ return STATUSBAR_ICON_POWER_30;
} else if (charge >= 15) {
- return TT_ASSETS_ICON_POWER_20;
+ return STATUSBAR_ICON_POWER_20;
} else if (charge >= 5) {
- return TT_ASSETS_ICON_POWER_10;
+ return STATUSBAR_ICON_POWER_10;
} else {
- return TT_ASSETS_ICON_POWER_0;
+ return STATUSBAR_ICON_POWER_0;
}
}
-static void update_power_icon(std::shared_ptr data) {
- const char* desired_icon = power_get_status_icon();
+static void updatePowerStatusIcon(const service::Paths* paths, const std::shared_ptr& data) {
+ const char* desired_icon = getPowerStatusIcon();
if (data->power_last_icon != desired_icon) {
- lvgl::statusbar_icon_set_image(data->power_icon_id, desired_icon);
- lvgl::statusbar_icon_set_visibility(data->power_icon_id, desired_icon != nullptr);
+ if (desired_icon != nullptr) {
+ auto icon_path = paths->getSystemPathLvgl(desired_icon);
+ lvgl::statusbar_icon_set_image(data->power_icon_id, icon_path);
+ lvgl::statusbar_icon_set_visibility(data->power_icon_id, true);
+ } else {
+ lvgl::statusbar_icon_set_visibility(data->power_icon_id, false);
+ }
data->power_last_icon = desired_icon;
}
}
@@ -177,9 +218,10 @@ static void service_data_free(ServiceData* data) {
static void onUpdate(std::shared_ptr parameter) {
auto data = std::static_pointer_cast(parameter);
// TODO: Make thread-safe for LVGL
- update_wifi_icon(data);
- update_sdcard_icon(data);
- update_power_icon(data);
+ auto* paths = data->paths.get();
+ updateWifiIcon(paths, data);
+ updateSdCardIcon(paths, data);
+ updatePowerStatusIcon(paths, data);
}
static void onStart(ServiceContext& service) {
@@ -187,13 +229,15 @@ static void onStart(ServiceContext& service) {
auto data = std::make_shared();
lvgl::unlock();
+ data->paths = std::move(service.getPaths());
+
service.setData(data);
// TODO: Make thread-safe for LVGL
lvgl::statusbar_icon_set_visibility(data->wifi_icon_id, true);
- update_wifi_icon(data);
- update_sdcard_icon(data); // also updates visibility
- update_power_icon(data);
+ updateWifiIcon(data->paths.get(), data);
+ updateSdCardIcon(data->paths.get(), data); // also updates visibility
+ updatePowerStatusIcon(data->paths.get(), data);
data->updateTimer = std::make_unique(Timer::TypePeriodic, onUpdate, data);
// We want to try and scan more often in case of startup or scan lock failure
diff --git a/TactilityCore/Source/Dispatcher.cpp b/TactilityCore/Source/Dispatcher.cpp
index 96caf755..eb1295bb 100644
--- a/TactilityCore/Source/Dispatcher.cpp
+++ b/TactilityCore/Source/Dispatcher.cpp
@@ -4,7 +4,7 @@
namespace tt {
-#define TAG "Dispatcher"
+#define TAG "dispatcher"
#define BACKPRESSURE_WARNING_COUNT 100
#define WAIT_FLAG 1
diff --git a/TactilityCore/Source/Log.cpp b/TactilityCore/Source/Log.cpp
index 04c9c96b..6b8f54bd 100644
--- a/TactilityCore/Source/Log.cpp
+++ b/TactilityCore/Source/Log.cpp
@@ -118,7 +118,7 @@ static uint64_t getTimestamp() {
void log(LogLevel level, const char* tag, const char* format, ...) {
std::stringstream buffer;
- buffer << toColour(level) << toPrefix(level) << " (" << getTimestamp() << ") " << tag << " " << format << "\033[0m\n";
+ buffer << toColour(level) << toPrefix(level) << " (" << getTimestamp() << ") " << tag << ": " << format << "\033[0m\n";
va_list args;
va_start(args, format);
diff --git a/TactilityCore/Source/file/File.cpp b/TactilityCore/Source/file/File.cpp
index 2c1bf40c..2759398f 100644
--- a/TactilityCore/Source/file/File.cpp
+++ b/TactilityCore/Source/file/File.cpp
@@ -49,7 +49,7 @@ static std::unique_ptr readBinaryInternal(const std::string& filepath
size_t buffer_offset = 0;
while (buffer_offset < content_length) {
size_t bytes_read = fread(&data.get()[buffer_offset], 1, content_length - buffer_offset, file);
- TT_LOG_I(TAG, "Read %d bytes", bytes_read);
+ TT_LOG_D(TAG, "Read %d bytes", bytes_read);
if (bytes_read > 0) {
buffer_offset += bytes_read;
} else { // Something went wrong?
@@ -71,11 +71,15 @@ std::unique_ptr readBinary(const std::string& filepath, size_t& outSi
std::unique_ptr readString(const std::string& filepath) {
size_t size = 0;
auto data = readBinaryInternal(filepath, size, 1);
- if (size > 0) {
+ if (data == nullptr) {
+ return nullptr;
+ } else if (size > 0) {
data.get()[size] = 0; // Append null terminator
return data;
- } else {
- return nullptr;
+ } else { // Empty file: return empty string
+ auto value = std::make_unique(1);
+ value[0] = 0;
+ return value;
}
}
diff --git a/TactilityHeadless/CMakeLists.txt b/TactilityHeadless/CMakeLists.txt
index 6ce8bcda..545ec491 100644
--- a/TactilityHeadless/CMakeLists.txt
+++ b/TactilityHeadless/CMakeLists.txt
@@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (DEFINED ENV{ESP_IDF_VERSION})
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
- list(APPEND REQUIRES_LIST TactilityCore esp_wifi nvs_flash driver spiffs vfs fatfs )
+ list(APPEND REQUIRES_LIST TactilityCore esp_wifi nvs_flash driver spiffs vfs fatfs)
if("${IDF_TARGET}" STREQUAL "esp32s3")
list(APPEND REQUIRES_LIST esp_tinyusb)
endif()
@@ -19,10 +19,10 @@ if (DEFINED ENV{ESP_IDF_VERSION})
)
if (NOT DEFINED TACTILITY_SKIP_SPIFFS)
- set(ASSETS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Data/assets")
- spiffs_create_partition_image(assets ${ASSETS_SRC_DIR} FLASH_IN_PROJECT)
- set(CONFIG_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Data/config")
- spiffs_create_partition_image(config ${CONFIG_SRC_DIR} FLASH_IN_PROJECT)
+ # Read-only
+ fatfs_create_rawflash_image(system "${CMAKE_CURRENT_SOURCE_DIR}/../Data/system" FLASH_IN_PROJECT PRESERVE_TIME)
+ # Read-write
+ fatfs_create_spiflash_image(data "${CMAKE_CURRENT_SOURCE_DIR}/../Data/data" FLASH_IN_PROJECT PRESERVE_TIME)
endif()
add_definitions(-DESP_PLATFORM)
diff --git a/TactilityHeadless/Private/EspPartitions_i.h b/TactilityHeadless/Private/EspPartitions_i.h
index 93d5ffc7..fb2abe52 100644
--- a/TactilityHeadless/Private/EspPartitions_i.h
+++ b/TactilityHeadless/Private/EspPartitions_i.h
@@ -6,7 +6,7 @@
namespace tt {
-esp_err_t initEspPartitions();
+esp_err_t initPartitionsEsp();
} // namespace
diff --git a/TactilityHeadless/Private/service/ServiceInstance.h b/TactilityHeadless/Private/service/ServiceInstance.h
index b3d9577f..d50682fd 100644
--- a/TactilityHeadless/Private/service/ServiceInstance.h
+++ b/TactilityHeadless/Private/service/ServiceInstance.h
@@ -20,6 +20,8 @@ public:
const service::ServiceManifest& getManifest() const override;
std::shared_ptr getData() const override;
void setData(std::shared_ptr newData) override;
+
+ std::unique_ptr getPaths() const override;
};
}
diff --git a/TactilityHeadless/Private/service/ServiceInstancePaths.h b/TactilityHeadless/Private/service/ServiceInstancePaths.h
new file mode 100644
index 00000000..ee95f16b
--- /dev/null
+++ b/TactilityHeadless/Private/service/ServiceInstancePaths.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "service/ServiceInstance.h"
+
+namespace tt::service {
+
+class ServiceInstancePaths final : public Paths {
+
+private:
+
+ const ServiceManifest& manifest;
+
+public:
+
+ explicit ServiceInstancePaths(const ServiceManifest& manifest) : manifest(manifest) {}
+ ~ServiceInstancePaths() final = default;
+
+ std::string getDataDirectory() const final;
+ std::string getDataDirectoryLvgl() const final;
+ std::string getDataPath(const std::string& childPath) const final;
+ std::string getDataPathLvgl(const std::string& childPath) const final;
+ std::string getSystemDirectory() const final;
+ std::string getSystemDirectoryLvgl() const final;
+ std::string getSystemPath(const std::string& childPath) const final;
+ std::string getSystemPathLvgl(const std::string& childPath) const final;
+};
+
+}
\ No newline at end of file
diff --git a/TactilityHeadless/Source/Assets.h b/TactilityHeadless/Source/Assets.h
index 8c3e715a..9536d1d5 100644
--- a/TactilityHeadless/Source/Assets.h
+++ b/TactilityHeadless/Source/Assets.h
@@ -1,12 +1,8 @@
#pragma once
-#define TT_ASSET_FOLDER "A:/assets/"
+#define TT_ASSET_FOLDER "A:/system/"
#define TT_ASSET(file) TT_ASSET_FOLDER file
-// Splash
-#define TT_ASSETS_BOOT_LOGO TT_ASSET("boot_logo.png")
-#define TT_ASSETS_BOOT_LOGO_USB TT_ASSET("boot_logo_usb.png")
-
// UI
#define TT_ASSETS_UI_SPINNER TT_ASSET("spinner.png")
@@ -18,32 +14,3 @@
#define TT_ASSETS_APP_ICON_I2C_SETTINGS TT_ASSET("app_icon_i2c.png")
#define TT_ASSETS_APP_ICON_SETTINGS TT_ASSET("app_icon_settings.png")
#define TT_ASSETS_APP_ICON_SYSTEM_INFO TT_ASSET("app_icon_system_info.png")
-
-// SD card status
-#define TT_ASSETS_ICON_SDCARD TT_ASSET("sdcard.png")
-#define TT_ASSETS_ICON_SDCARD_ALERT TT_ASSET("sdcard_alert.png")
-
-// Wifi status
-#define TT_ASSETS_ICON_WIFI_OFF_WHITE TT_ASSET("wifi_off_white.png")
-#define TT_ASSETS_ICON_WIFI_SCAN_WHITE TT_ASSET("wifi_scan_white.png")
-#define TT_ASSETS_ICON_WIFI_SIGNAL_WEAK_WHITE TT_ASSET("wifi_signal_weak_white.png")
-#define TT_ASSETS_ICON_WIFI_SIGNAL_MEDIUM_WHITE TT_ASSET("wifi_signal_medium_white.png")
-#define TT_ASSETS_ICON_WIFI_SIGNAL_STRONG_WHITE TT_ASSET("wifi_signal_strong_white.png")
-// Black (Wifi Manage)
-#define TT_ASSETS_ICON_WIFI_LOCK_BLACK TT_ASSET("wifi_lock_black.png")
-#define TT_ASSETS_ICON_WIFI_SIGNAL_WEAK_BLACK TT_ASSET("wifi_signal_weak_black.png")
-#define TT_ASSETS_ICON_WIFI_SIGNAL_MEDIUM_BLACK TT_ASSET("wifi_signal_medium_black.png")
-#define TT_ASSETS_ICON_WIFI_SIGNAL_STRONG_BLACK TT_ASSET("wifi_signal_strong_black.png")
-
-// Power status
-#define TT_ASSETS_ICON_POWER_0 TT_ASSET("power_0.png")
-#define TT_ASSETS_ICON_POWER_10 TT_ASSET("power_10.png")
-#define TT_ASSETS_ICON_POWER_20 TT_ASSET("power_20.png")
-#define TT_ASSETS_ICON_POWER_30 TT_ASSET("power_30.png")
-#define TT_ASSETS_ICON_POWER_40 TT_ASSET("power_40.png")
-#define TT_ASSETS_ICON_POWER_50 TT_ASSET("power_50.png")
-#define TT_ASSETS_ICON_POWER_60 TT_ASSET("power_60.png")
-#define TT_ASSETS_ICON_POWER_70 TT_ASSET("power_70.png")
-#define TT_ASSETS_ICON_POWER_80 TT_ASSET("power_80.png")
-#define TT_ASSETS_ICON_POWER_90 TT_ASSET("power_90.png")
-#define TT_ASSETS_ICON_POWER_100 TT_ASSET("power_100.png")
diff --git a/TactilityHeadless/Source/EspPartitions.cpp b/TactilityHeadless/Source/EspPartitions.cpp
deleted file mode 100644
index b578e3bc..00000000
--- a/TactilityHeadless/Source/EspPartitions.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifdef ESP_TARGET
-
-#include "EspPartitions.h"
-#include "EspPartitions_i.h"
-#include "Log.h"
-
-#include "esp_spiffs.h"
-#include "nvs_flash.h"
-
-namespace tt {
-
-static const char* TAG = "filesystem";
-
-static esp_err_t initNvsFlashSafely() {
- esp_err_t result = nvs_flash_init();
- if (result == ESP_ERR_NVS_NO_FREE_PAGES || result == ESP_ERR_NVS_NEW_VERSION_FOUND) {
- ESP_ERROR_CHECK(nvs_flash_erase());
- result = nvs_flash_init();
- }
- return result;
-}
-
-static esp_err_t initSpiffs(esp_vfs_spiffs_conf_t* conf) {
- esp_err_t ret = esp_vfs_spiffs_register(conf);
- if (ret != ESP_OK) {
- if (ret == ESP_FAIL) {
- TT_LOG_E(TAG, "Failed to mount or format filesystem %s", conf->base_path);
- } else if (ret == ESP_ERR_NOT_FOUND) {
- TT_LOG_E(TAG, "Failed to find SPIFFS partition %s", conf->base_path);
- } else {
- TT_LOG_E(TAG, "Failed to initialize SPIFFS %s (%s)", conf->base_path, esp_err_to_name(ret));
- }
- return ESP_FAIL;
- }
-
- size_t total = -1, used = 0;
- ret = esp_spiffs_info(NULL, &total, &used);
- if (ret != ESP_OK) {
- TT_LOG_E(TAG, "Failed to get SPIFFS partition information for %s (%s)", conf->base_path, esp_err_to_name(ret));
- } else {
- TT_LOG_I(TAG, "Partition size for %s: total: %d, used: %d", conf->base_path, total, used);
- }
- return ESP_OK;
-}
-
-esp_err_t initEspPartitions() {
- ESP_ERROR_CHECK(initNvsFlashSafely());
-
- esp_vfs_spiffs_conf_t assets_spiffs = {
- .base_path = MOUNT_POINT_ASSETS,
- .partition_label = NULL,
- .max_files = 100,
- .format_if_mount_failed = false
- };
-
- if (initSpiffs(&assets_spiffs) != ESP_OK) {
- return ESP_FAIL;
- }
-
- esp_vfs_spiffs_conf_t config_spiffs = {
- .base_path = MOUNT_POINT_CONFIG,
- .partition_label = "config",
- .max_files = 100,
- .format_if_mount_failed = false
- };
-
- if (initSpiffs(&config_spiffs) != ESP_OK) {
- return ESP_FAIL;
- }
-
- return ESP_OK;
-}
-
-} // namespace
-
-#endif // ESP_TARGET
diff --git a/TactilityHeadless/Source/EspPartitions.h b/TactilityHeadless/Source/EspPartitions.h
deleted file mode 100644
index 6ef8562d..00000000
--- a/TactilityHeadless/Source/EspPartitions.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-#ifdef ESP_TARGET
-
-namespace tt {
-
-#define MOUNT_POINT_ASSETS "/assets"
-#define MOUNT_POINT_CONFIG "/config"
-
-} // namespace
-
-#endif // ESP_TARGET
\ No newline at end of file
diff --git a/TactilityHeadless/Source/Partitions.h b/TactilityHeadless/Source/Partitions.h
new file mode 100644
index 00000000..78f4eca0
--- /dev/null
+++ b/TactilityHeadless/Source/Partitions.h
@@ -0,0 +1,21 @@
+#pragma once
+
+namespace tt {
+
+#define SYSTEM_PARTITION_NAME "system"
+
+#ifdef ESP_PLATFORM
+#define MOUNT_POINT_SYSTEM "/system"
+#else
+#define MOUNT_POINT_SYSTEM "system"
+#endif
+
+#define DATA_PARTITION_NAME "data"
+
+#ifdef ESP_PLATFORM
+#define MOUNT_POINT_DATA "/data"
+#else
+#define MOUNT_POINT_DATA "data"
+#endif
+
+} // namespace
diff --git a/TactilityHeadless/Source/PartitionsEsp.cpp b/TactilityHeadless/Source/PartitionsEsp.cpp
new file mode 100644
index 00000000..0ba83ae3
--- /dev/null
+++ b/TactilityHeadless/Source/PartitionsEsp.cpp
@@ -0,0 +1,54 @@
+#ifdef ESP_TARGET
+
+#include "EspPartitions_i.h"
+#include "Log.h"
+
+#include
+#include
+
+namespace tt {
+
+static const char* TAG = "partitions";
+
+static esp_err_t initNvsFlashSafely() {
+ esp_err_t result = nvs_flash_init();
+ if (result == ESP_ERR_NVS_NO_FREE_PAGES || result == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+ ESP_ERROR_CHECK(nvs_flash_erase());
+ result = nvs_flash_init();
+ }
+ return result;
+}
+
+static wl_handle_t data_wl_handle = WL_INVALID_HANDLE;
+
+esp_err_t initPartitionsEsp() {
+ ESP_ERROR_CHECK(initNvsFlashSafely());
+
+ const esp_vfs_fat_mount_config_t mount_config = {
+ .format_if_mount_failed = false,
+ .max_files = 4,
+ .allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
+ .disk_status_check_enable = false,
+ .use_one_fat = true,
+ };
+
+ auto system_result = esp_vfs_fat_spiflash_mount_ro("/system", "system", &mount_config);
+ if (system_result != ESP_OK) {
+ TT_LOG_E(TAG, "Failed to mount /system (%s)", esp_err_to_name(system_result));
+ } else {
+ TT_LOG_I(TAG, "Mounted /system");
+ }
+
+ auto data_result = esp_vfs_fat_spiflash_mount_rw_wl("/data", "data", &mount_config, &data_wl_handle);
+ if (data_result != ESP_OK) {
+ TT_LOG_E(TAG, "Failed to mount /data (%s)", esp_err_to_name(data_result));
+ } else {
+ TT_LOG_I(TAG, "Mounted /data");
+ }
+
+ return system_result == ESP_OK && data_result == ESP_OK;
+}
+
+} // namespace
+
+#endif // ESP_TARGET
diff --git a/TactilityHeadless/Source/EspInit.cpp b/TactilityHeadless/Source/TactilityHeadlessEsp.cpp
similarity index 83%
rename from TactilityHeadless/Source/EspInit.cpp
rename to TactilityHeadless/Source/TactilityHeadlessEsp.cpp
index 204f6d47..e27b35ae 100644
--- a/TactilityHeadless/Source/EspInit.cpp
+++ b/TactilityHeadless/Source/TactilityHeadlessEsp.cpp
@@ -1,7 +1,5 @@
-#include "TactilityCore.h"
-
#ifdef ESP_TARGET
-
+#include "TactilityCore.h"
#include "EspPartitions_i.h"
#include "esp_event.h"
@@ -13,7 +11,7 @@ namespace tt {
#define TAG "tactility"
// Initialize NVS
-static void initEspNvs() {
+static void initNvs() {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
TT_LOG_I(TAG, "nvs erasing");
@@ -24,15 +22,15 @@ static void initEspNvs() {
TT_LOG_I(TAG, "nvs initialized");
}
-static void initEspNetwork() {
+static void initNetwork() {
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
}
void initEsp() {
- initEspNvs();
- initEspPartitions();
- initEspNetwork();
+ initNvs();
+ initPartitionsEsp();
+ initNetwork();
}
} // namespace
diff --git a/TactilityHeadless/Source/hal/Hal.cpp b/TactilityHeadless/Source/hal/Hal.cpp
index 16b430d7..2feb470d 100644
--- a/TactilityHeadless/Source/hal/Hal.cpp
+++ b/TactilityHeadless/Source/hal/Hal.cpp
@@ -19,7 +19,7 @@ void init(const Configuration& configuration) {
if (configuration.sdcard != nullptr) {
TT_LOG_I(TAG, "Mounting sdcard");
- if (!configuration.sdcard->mount(TT_SDCARD_MOUNT_POINT )) {
+ if (!configuration.sdcard->mount(TT_SDCARD_MOUNT_POINT)) {
TT_LOG_W(TAG, "SD card mount failed (init can continue)");
}
}
diff --git a/TactilityHeadless/Source/hal/SdCard.h b/TactilityHeadless/Source/hal/SdCard.h
index 48736396..3b7266dd 100644
--- a/TactilityHeadless/Source/hal/SdCard.h
+++ b/TactilityHeadless/Source/hal/SdCard.h
@@ -4,6 +4,7 @@
namespace tt::hal {
+#define TT_SDCARD_MOUNT_NAME "sdcard"
#define TT_SDCARD_MOUNT_POINT "/sdcard"
class SdCard {
diff --git a/TactilityHeadless/Source/service/ServiceContext.h b/TactilityHeadless/Source/service/ServiceContext.h
index 9473d800..8c27af7a 100644
--- a/TactilityHeadless/Source/service/ServiceContext.h
+++ b/TactilityHeadless/Source/service/ServiceContext.h
@@ -6,6 +6,8 @@
namespace tt::service {
+class Paths;
+
class ServiceContext {
protected:
@@ -17,6 +19,68 @@ public:
virtual const service::ServiceManifest& getManifest() const = 0;
virtual std::shared_ptr getData() const = 0;
virtual void setData(std::shared_ptr newData) = 0;
+ virtual std::unique_ptr getPaths() const = 0;
+};
+
+class Paths {
+
+public:
+
+ Paths() = default;
+ virtual ~Paths() = default;
+
+ /**
+ * Returns the directory path for the data location for a service.
+ * The data directory is intended to survive OS upgrades.
+ * The path will not end with a "/".
+ */
+ virtual std::string getDataDirectory() const = 0;
+
+ /**
+ * @see getDataDirectory(), but with LVGL prefix.
+ */
+ virtual std::string getDataDirectoryLvgl() const = 0;
+
+ /**
+ * Returns the full path for an entry inside the data location for a service.
+ * The data directory is intended to survive OS upgrades.
+ * Configuration data should be stored here.
+ * @param[in] childPath the path without a "/" prefix
+ */
+ virtual std::string getDataPath(const std::string& childPath) const = 0;
+
+ /**
+ * @see getDataPath(), but with LVGL prefix.
+ */
+ virtual std::string getDataPathLvgl(const std::string& childPath) const = 0;
+
+ /**
+ * Returns the directory path for the system location for a service.
+ * The system directory is not intended to survive OS upgrades.
+ * You should not store configuration data here.
+ * The path will not end with a "/".
+ * This is mainly used for core services.
+ */
+ virtual std::string getSystemDirectory() const = 0;
+
+ /**
+ * @see getSystemDirectory(), but with LVGL prefix.
+ */
+ virtual std::string getSystemDirectoryLvgl() const = 0;
+
+ /**
+ * Returns the full path for an entry inside the system location for an app.
+ * The data directory is not intended to survive OS upgrades.
+ * You should not store configuration data here.
+ * This is mainly used for core apps (system/boot/settings type).
+ * @param[in] childPath the path without a "/" prefix
+ */
+ virtual std::string getSystemPath(const std::string& childPath) const = 0;
+
+ /**
+ * @see getSystemPath(), but with LVGL prefix.
+ */
+ virtual std::string getSystemPathLvgl(const std::string& childPath) const = 0;
};
} // namespace
diff --git a/TactilityHeadless/Source/service/ServiceInstance.cpp b/TactilityHeadless/Source/service/ServiceInstance.cpp
index ad992cef..5dea1c8f 100644
--- a/TactilityHeadless/Source/service/ServiceInstance.cpp
+++ b/TactilityHeadless/Source/service/ServiceInstance.cpp
@@ -1,6 +1,7 @@
#include
#include "service/ServiceInstance.h"
+#include "service/ServiceInstancePaths.h"
namespace tt::service {
@@ -21,4 +22,8 @@ void ServiceInstance::setData(std::shared_ptr newData) {
mutex.release();
}
+std::unique_ptr ServiceInstance::getPaths() const {
+ return std::make_unique(manifest);
+}
+
}
\ No newline at end of file
diff --git a/TactilityHeadless/Source/service/ServiceInstancePaths.cpp b/TactilityHeadless/Source/service/ServiceInstancePaths.cpp
new file mode 100644
index 00000000..9c1faaf1
--- /dev/null
+++ b/TactilityHeadless/Source/service/ServiceInstancePaths.cpp
@@ -0,0 +1,48 @@
+#include "service/ServiceInstancePaths.h"
+#include "Partitions.h"
+
+#define LVGL_PATH_PREFIX std::string("A:/")
+#ifdef ESP_PLATFORM
+#define PARTITION_PREFIX std::string("/")
+#else
+#define PARTITION_PREFIX std::string("")
+#endif
+
+namespace tt::service {
+
+std::string ServiceInstancePaths::getDataDirectory() const {
+ return PARTITION_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id;
+}
+
+std::string ServiceInstancePaths::getDataDirectoryLvgl() const {
+ return LVGL_PATH_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id;
+}
+
+std::string ServiceInstancePaths::getDataPath(const std::string& childPath) const {
+ assert(!childPath.starts_with('/'));
+ return PARTITION_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
+}
+
+std::string ServiceInstancePaths::getDataPathLvgl(const std::string& childPath) const {
+ assert(!childPath.starts_with('/'));
+ return LVGL_PATH_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
+}
+
+std::string ServiceInstancePaths::getSystemDirectory() const {
+ return PARTITION_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id;
+}
+
+std::string ServiceInstancePaths::getSystemDirectoryLvgl() const {
+ return LVGL_PATH_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id;
+}
+
+std::string ServiceInstancePaths::getSystemPath(const std::string& childPath) const {
+ assert(!childPath.starts_with('/'));
+ return PARTITION_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
+}
+
+std::string ServiceInstancePaths::getSystemPathLvgl(const std::string& childPath) const {
+ return LVGL_PATH_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
+}
+
+}
diff --git a/partitions.csv b/partitions.csv
index 6a8f899b..3bc4b6f9 100644
--- a/partitions.csv
+++ b/partitions.csv
@@ -3,5 +3,5 @@
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 3M,
-assets, data, spiffs, , 128k,
-config, data, spiffs, , 64k,
+system, data, fat, , 256k,
+data, data, fat, , 256k,
diff --git a/sdkconfig.board.lilygo-tdeck b/sdkconfig.board.lilygo-tdeck
index 9ed497c8..7f991e02 100644
--- a/sdkconfig.board.lilygo-tdeck
+++ b/sdkconfig.board.lilygo-tdeck
@@ -1,4 +1,6 @@
# Software defaults
+# Increase stack size for WiFi (fixes crash after scan)
+CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_USE_USER_DATA=y
@@ -24,8 +26,7 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y
-CONFIG_TINYUSB_MSC_ENABLED=y
-CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
+CONFIG_FATFS_VOLUME_COUNT=3
# Hardware: Main
CONFIG_TT_BOARD_LILYGO_TDECK=y
@@ -44,3 +45,6 @@ CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_LV_DISP_DEF_REFR_PERIOD=17
CONFIG_LV_INDEV_DEF_READ_PERIOD=17
CONFIG_LV_DPI_DEF=139
+# USB
+CONFIG_TINYUSB_MSC_ENABLED=y
+CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
diff --git a/sdkconfig.board.m5stack-core2 b/sdkconfig.board.m5stack-core2
index 2e593b50..508494e3 100644
--- a/sdkconfig.board.m5stack-core2
+++ b/sdkconfig.board.m5stack-core2
@@ -1,4 +1,6 @@
# Software defaults
+# Increase stack size for WiFi (fixes crash after scan)
+CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_USE_USER_DATA=y
@@ -24,6 +26,7 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y
+CONFIG_FATFS_VOLUME_COUNT=3
# Hardware: Main
CONFIG_TT_BOARD_M5STACK_CORE2=y
@@ -32,7 +35,6 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_FLASHMODE_QIO=y
-CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
# Hardware: SPI RAM
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
@@ -42,3 +44,8 @@ CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_LV_DISP_DEF_REFR_PERIOD=17
CONFIG_LV_INDEV_DEF_READ_PERIOD=17
CONFIG_LV_DPI_DEF=139
+# Fix for IRAM
+CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
+CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
+CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH=y
+CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
diff --git a/sdkconfig.board.m5stack-cores3 b/sdkconfig.board.m5stack-cores3
index 9cc6b8cb..da65dc52 100644
--- a/sdkconfig.board.m5stack-cores3
+++ b/sdkconfig.board.m5stack-cores3
@@ -1,4 +1,6 @@
# Software defaults
+# Increase stack size for WiFi (fixes crash after scan)
+CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_USE_USER_DATA=y
@@ -24,8 +26,7 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y
-CONFIG_TINYUSB_MSC_ENABLED=y
-CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
+CONFIG_FATFS_VOLUME_COUNT=3
# Hardware: Main
CONFIG_TT_BOARD_M5STACK_CORES3=y
@@ -34,7 +35,6 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_FLASHMODE_QIO=y
-CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
# Hardware: SPI RAM
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_QUAD=y
@@ -50,3 +50,6 @@ CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_LV_DISP_DEF_REFR_PERIOD=17
CONFIG_LV_INDEV_DEF_READ_PERIOD=17
CONFIG_LV_DPI_DEF=139
+# USB
+CONFIG_TINYUSB_MSC_ENABLED=y
+CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
diff --git a/sdkconfig.board.yellow-board b/sdkconfig.board.yellow-board
index a41eb57a..462c8799 100644
--- a/sdkconfig.board.yellow-board
+++ b/sdkconfig.board.yellow-board
@@ -1,4 +1,6 @@
# Software defaults
+# Increase stack size for WiFi (fixes crash after scan)
+CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_USE_USER_DATA=y
@@ -24,6 +26,7 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y
+CONFIG_FATFS_VOLUME_COUNT=3
# Hardware: Main
CONFIG_TT_BOARD_YELLOW_BOARD_24_CAP=y
@@ -36,3 +39,8 @@ CONFIG_FLASHMODE_QIO=y
CONFIG_LV_DISP_DEF_REFR_PERIOD=17
CONFIG_LV_INDEV_DEF_READ_PERIOD=17
CONFIG_LV_DPI_DEF=160
+# Fix for IRAM
+CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
+CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
+CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH=y
+CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
diff --git a/sdkconfig.defaults b/sdkconfig.defaults
index 97e96523..db740a9a 100644
--- a/sdkconfig.defaults
+++ b/sdkconfig.defaults
@@ -1,4 +1,6 @@
# Software defaults
+# Increase stack size for WiFi (fixes crash after scan)
+CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_USE_USER_DATA=y
@@ -23,8 +25,8 @@ CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
-CONFIG_TINYUSB_MSC_ENABLED=y
-CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
+CONFIG_FATFS_LFN_HEAP=y
+CONFIG_FATFS_VOLUME_COUNT=3
# Hardware defaults
CONFIG_TT_BOARD_CUSTOM=y