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