diff --git a/app-sim/src/lv_conf.h b/app-sim/src/lv_conf.h
index facf78d8..d67011c4 100644
--- a/app-sim/src/lv_conf.h
+++ b/app-sim/src/lv_conf.h
@@ -572,8 +572,8 @@
/*API for fopen, fread, etc*/
#define LV_USE_FS_STDIO 1
#if LV_USE_FS_STDIO
- #define LV_FS_STDIO_LETTER 'A' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
- #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
+ #define LV_FS_STDIO_LETTER 'A' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
+ #define LV_FS_STDIO_PATH "." /*Set the working directory. File/directory paths will be appended to it.*/
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
diff --git a/boards/lilygo_tdeck/sdcard.c b/boards/lilygo_tdeck/sdcard.c
index c662c4e6..93d896e4 100644
--- a/boards/lilygo_tdeck/sdcard.c
+++ b/boards/lilygo_tdeck/sdcard.c
@@ -54,7 +54,7 @@ static bool sdcard_init() {
return true;
}
-static void* sdcard_mount(const char* mount_point) {
+static void* _Nullable sdcard_mount(const char* mount_point) {
TT_LOG_I(TAG, "Mounting %s", mount_point);
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
@@ -64,8 +64,6 @@ static void* sdcard_mount(const char* mount_point) {
.disk_status_check_enable = TDECK_SDCARD_STATUS_CHECK_ENABLED
};
- sdmmc_card_t* card;
-
// Init without card detect (CD) and write protect (WD)
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = TDECK_SDCARD_PIN_CS;
@@ -76,6 +74,8 @@ static void* sdcard_mount(const char* mount_point) {
// https://github.com/Xinyuan-LilyGO/T-Deck/blob/master/examples/UnitTest/UnitTest.ino
// Observation: Using this automatically sets the bus to 20MHz
host.max_freq_khz = TDECK_SDCARD_SPI_FREQUENCY;
+
+ sdmmc_card_t* card;
esp_err_t ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
@@ -101,7 +101,6 @@ static void* sdcard_init_and_mount(const char* mount_point) {
TT_LOG_E(TAG, "Failed to set SPI CS pins high. This is a pre-requisite for mounting.");
return NULL;
}
-
MountData* data = sdcard_mount(mount_point);
if (data == NULL) {
TT_LOG_E(TAG, "Mount failed for %s", mount_point);
@@ -125,8 +124,14 @@ static void sdcard_unmount(void* context) {
free(data);
}
+static bool sdcard_is_mounted(void* context) {
+ MountData* data = (MountData*)context;
+ return (data != NULL) && (sdmmc_get_status(data->card) == ESP_OK);
+}
+
const SdCard tdeck_sdcard = {
.mount = &sdcard_init_and_mount,
.unmount = &sdcard_unmount,
+ .is_mounted = &sdcard_is_mounted,
.mount_behaviour = SDCARD_MOUNT_BEHAVIOUR_AT_BOOT
};
diff --git a/boards/yellow_board/sdcard.c b/boards/yellow_board/sdcard.c
index c8cc18e1..d9aaec08 100644
--- a/boards/yellow_board/sdcard.c
+++ b/boards/yellow_board/sdcard.c
@@ -66,8 +66,14 @@ static void sdcard_unmount(void* context) {
free(data);
}
+static bool sdcard_is_mounted(void* context) {
+ MountData* data = (MountData*)context;
+ return (data != NULL) && (sdmmc_get_status(data->card) == ESP_OK);
+}
+
const SdCard twodotfour_sdcard = {
.mount = &sdcard_mount,
.unmount = &sdcard_unmount,
+ .is_mounted = &sdcard_is_mounted,
.mount_behaviour = SDCARD_MOUNT_BEHAVIOUR_ANYTIME
};
diff --git a/data/assets/sdcard.png b/data/assets/sdcard.png
new file mode 100644
index 00000000..6c222e11
Binary files /dev/null and b/data/assets/sdcard.png differ
diff --git a/data/assets/sdcard_alert.png b/data/assets/sdcard_alert.png
new file mode 100644
index 00000000..933c8465
Binary files /dev/null and b/data/assets/sdcard_alert.png differ
diff --git a/data/assets/wifi_connection_issue.png b/data/assets/wifi_connection_issue.png
new file mode 100644
index 00000000..5c79dbdb
Binary files /dev/null and b/data/assets/wifi_connection_issue.png differ
diff --git a/data/assets/wifi_find.png b/data/assets/wifi_find.png
new file mode 100644
index 00000000..f20ab74f
Binary files /dev/null and b/data/assets/wifi_find.png differ
diff --git a/data/assets/wifi_off.png b/data/assets/wifi_off.png
new file mode 100644
index 00000000..983b1792
Binary files /dev/null and b/data/assets/wifi_off.png differ
diff --git a/data/assets/wifi_perm_scan.png b/data/assets/wifi_perm_scan.png
new file mode 100644
index 00000000..c6b668d7
Binary files /dev/null and b/data/assets/wifi_perm_scan.png differ
diff --git a/data/assets/wifi_signal_0.png b/data/assets/wifi_signal_0.png
new file mode 100644
index 00000000..964d0ee2
Binary files /dev/null and b/data/assets/wifi_signal_0.png differ
diff --git a/data/assets/wifi_signal_0_lock.png b/data/assets/wifi_signal_0_lock.png
new file mode 100644
index 00000000..6c569446
Binary files /dev/null and b/data/assets/wifi_signal_0_lock.png differ
diff --git a/data/assets/wifi_signal_1.png b/data/assets/wifi_signal_1.png
new file mode 100644
index 00000000..7799eeda
Binary files /dev/null and b/data/assets/wifi_signal_1.png differ
diff --git a/data/assets/wifi_signal_1_locked.png b/data/assets/wifi_signal_1_locked.png
new file mode 100644
index 00000000..7f3759d7
Binary files /dev/null and b/data/assets/wifi_signal_1_locked.png differ
diff --git a/data/assets/wifi_signal_2.png b/data/assets/wifi_signal_2.png
new file mode 100644
index 00000000..1da91111
Binary files /dev/null and b/data/assets/wifi_signal_2.png differ
diff --git a/data/assets/wifi_signal_2_locked.png b/data/assets/wifi_signal_2_locked.png
new file mode 100644
index 00000000..d26417f4
Binary files /dev/null and b/data/assets/wifi_signal_2_locked.png differ
diff --git a/data/assets/wifi_signal_3.png b/data/assets/wifi_signal_3.png
new file mode 100644
index 00000000..89ff66b2
Binary files /dev/null and b/data/assets/wifi_signal_3.png differ
diff --git a/data/assets/wifi_signal_3_locked.png b/data/assets/wifi_signal_3_locked.png
new file mode 100644
index 00000000..40d4b10a
Binary files /dev/null and b/data/assets/wifi_signal_3_locked.png differ
diff --git a/data/assets/wifi_signal_4.png b/data/assets/wifi_signal_4.png
new file mode 100644
index 00000000..e5b1b108
Binary files /dev/null and b/data/assets/wifi_signal_4.png differ
diff --git a/data/assets/wifi_signal_4_locked.png b/data/assets/wifi_signal_4_locked.png
new file mode 100644
index 00000000..c08dfc89
Binary files /dev/null and b/data/assets/wifi_signal_4_locked.png differ
diff --git a/data/assets_sources/sdcard.svg b/data/assets_sources/sdcard.svg
new file mode 100644
index 00000000..d250daab
--- /dev/null
+++ b/data/assets_sources/sdcard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/sdcard_alert.svg b/data/assets_sources/sdcard_alert.svg
new file mode 100644
index 00000000..565c6856
--- /dev/null
+++ b/data/assets_sources/sdcard_alert.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_connection_issue.svg b/data/assets_sources/wifi_connection_issue.svg
new file mode 100644
index 00000000..0c527912
--- /dev/null
+++ b/data/assets_sources/wifi_connection_issue.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_find.svg b/data/assets_sources/wifi_find.svg
new file mode 100644
index 00000000..97f271a4
--- /dev/null
+++ b/data/assets_sources/wifi_find.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_off.svg b/data/assets_sources/wifi_off.svg
new file mode 100644
index 00000000..bd0d4cc2
--- /dev/null
+++ b/data/assets_sources/wifi_off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_perm_scan.svg b/data/assets_sources/wifi_perm_scan.svg
new file mode 100644
index 00000000..71708f75
--- /dev/null
+++ b/data/assets_sources/wifi_perm_scan.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_0.svg b/data/assets_sources/wifi_signal_0.svg
new file mode 100644
index 00000000..63c9ecfb
--- /dev/null
+++ b/data/assets_sources/wifi_signal_0.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_0_lock.svg b/data/assets_sources/wifi_signal_0_lock.svg
new file mode 100644
index 00000000..50b38476
--- /dev/null
+++ b/data/assets_sources/wifi_signal_0_lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_1.svg b/data/assets_sources/wifi_signal_1.svg
new file mode 100644
index 00000000..9cc573d1
--- /dev/null
+++ b/data/assets_sources/wifi_signal_1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_1_locked.svg b/data/assets_sources/wifi_signal_1_locked.svg
new file mode 100644
index 00000000..c8a7e5a9
--- /dev/null
+++ b/data/assets_sources/wifi_signal_1_locked.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_2.svg b/data/assets_sources/wifi_signal_2.svg
new file mode 100644
index 00000000..dee8e30b
--- /dev/null
+++ b/data/assets_sources/wifi_signal_2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_2_locked.svg b/data/assets_sources/wifi_signal_2_locked.svg
new file mode 100644
index 00000000..075d61d5
--- /dev/null
+++ b/data/assets_sources/wifi_signal_2_locked.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_3.svg b/data/assets_sources/wifi_signal_3.svg
new file mode 100644
index 00000000..f9709047
--- /dev/null
+++ b/data/assets_sources/wifi_signal_3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_3_locked.svg b/data/assets_sources/wifi_signal_3_locked.svg
new file mode 100644
index 00000000..82f7bf33
--- /dev/null
+++ b/data/assets_sources/wifi_signal_3_locked.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_4.svg b/data/assets_sources/wifi_signal_4.svg
new file mode 100644
index 00000000..92d41ac4
--- /dev/null
+++ b/data/assets_sources/wifi_signal_4.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_4_locked.svg b/data/assets_sources/wifi_signal_4_locked.svg
new file mode 100644
index 00000000..9e22d11a
--- /dev/null
+++ b/data/assets_sources/wifi_signal_4_locked.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/assets_sources/wifi_signal_5.svg b/data/assets_sources/wifi_signal_5.svg
new file mode 100644
index 00000000..249ab46f
--- /dev/null
+++ b/data/assets_sources/wifi_signal_5.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tactility-esp/config/placeholder.txt b/data/config/placeholder.txt
similarity index 100%
rename from tactility-esp/config/placeholder.txt
rename to data/config/placeholder.txt
diff --git a/tactility-core/src/pubsub.c b/tactility-core/src/pubsub.c
index 7bb65f7f..4fcfc227 100644
--- a/tactility-core/src/pubsub.c
+++ b/tactility-core/src/pubsub.c
@@ -13,7 +13,7 @@ LIST_DEF(PubSubSubscriptionList, PubSubSubscription, M_POD_OPLIST);
struct PubSub {
PubSubSubscriptionList_t items;
- Mutex* mutex;
+ Mutex mutex;
};
PubSub* tt_pubsub_alloc() {
diff --git a/tactility-core/src/thread.c b/tactility-core/src/thread.c
index 0ce968b5..21c732b2 100644
--- a/tactility-core/src/thread.c
+++ b/tactility-core/src/thread.c
@@ -80,7 +80,6 @@ static void tt_thread_body(void* context) {
tt_thread_set_state(thread, ThreadStateRunning);
thread->ret = thread->callback(thread->context);
- TT_LOG_I(TAG, "thread returned: %s", thread->name ?: "[no name]");
tt_assert(thread->state == ThreadStateRunning);
@@ -170,7 +169,7 @@ void tt_thread_mark_as_static(Thread* thread) {
thread->is_static = true;
}
-bool tt_thread_mark_is_service(ThreadId thread_id) {
+bool tt_thread_mark_is_static(ThreadId thread_id) {
TaskHandle_t hTask = (TaskHandle_t)thread_id;
assert(!TT_IS_IRQ_MODE() && (hTask != NULL));
Thread* thread = (Thread*)pvTaskGetThreadLocalStoragePointer(hTask, 0);
diff --git a/tactility-core/src/thread.h b/tactility-core/src/thread.h
index c04b5795..707c6fe2 100644
--- a/tactility-core/src/thread.h
+++ b/tactility-core/src/thread.h
@@ -275,7 +275,12 @@ void tt_thread_resume(ThreadId thread_id);
*/
bool tt_thread_is_suspended(ThreadId thread_id);
-bool tt_thread_mark_is_service(ThreadId thread_id);
+/** Check if the thread was created with static memory
+ *
+ * @param thread_id thread id
+ * @return true if thread memory is static
+ */
+bool tt_thread_mark_is_static(ThreadId thread_id);
#ifdef __cplusplus
}
diff --git a/tactility-esp/CMakeLists.txt b/tactility-esp/CMakeLists.txt
index 66214679..c759af9e 100644
--- a/tactility-esp/CMakeLists.txt
+++ b/tactility-esp/CMakeLists.txt
@@ -10,10 +10,10 @@ idf_component_register(
REQUIRES esp_wifi nvs_flash spiffs
)
-set(ASSETS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets")
+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}/config")
+set(CONFIG_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../data/config")
spiffs_create_partition_image(config ${CONFIG_SRC_DIR} FLASH_IN_PROJECT)
target_link_libraries(${COMPONENT_LIB} ${IDF_TARGET_NAME} tactility)
diff --git a/tactility-esp/assets/ic_small_wifi_off.png b/tactility-esp/assets/ic_small_wifi_off.png
deleted file mode 100644
index c27a2815..00000000
Binary files a/tactility-esp/assets/ic_small_wifi_off.png and /dev/null differ
diff --git a/tactility-esp/assets/ic_small_wifi_on.png b/tactility-esp/assets/ic_small_wifi_on.png
deleted file mode 100644
index 7e3141c8..00000000
Binary files a/tactility-esp/assets/ic_small_wifi_on.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi.png b/tactility-esp/assets/network_wifi.png
deleted file mode 100644
index 00c107a1..00000000
Binary files a/tactility-esp/assets/network_wifi.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_1_bar.png b/tactility-esp/assets/network_wifi_1_bar.png
deleted file mode 100644
index a181c191..00000000
Binary files a/tactility-esp/assets/network_wifi_1_bar.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_1_bar_locked.png b/tactility-esp/assets/network_wifi_1_bar_locked.png
deleted file mode 100644
index 1b59d794..00000000
Binary files a/tactility-esp/assets/network_wifi_1_bar_locked.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_2_bar.png b/tactility-esp/assets/network_wifi_2_bar.png
deleted file mode 100644
index 82b45eb4..00000000
Binary files a/tactility-esp/assets/network_wifi_2_bar.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_2_bar_locked.png b/tactility-esp/assets/network_wifi_2_bar_locked.png
deleted file mode 100644
index ca2c8f67..00000000
Binary files a/tactility-esp/assets/network_wifi_2_bar_locked.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_3_bar.png b/tactility-esp/assets/network_wifi_3_bar.png
deleted file mode 100644
index c07627de..00000000
Binary files a/tactility-esp/assets/network_wifi_3_bar.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_3_bar_locked.png b/tactility-esp/assets/network_wifi_3_bar_locked.png
deleted file mode 100644
index b9596cfe..00000000
Binary files a/tactility-esp/assets/network_wifi_3_bar_locked.png and /dev/null differ
diff --git a/tactility-esp/assets/network_wifi_locked.png b/tactility-esp/assets/network_wifi_locked.png
deleted file mode 100644
index cfd4f35c..00000000
Binary files a/tactility-esp/assets/network_wifi_locked.png and /dev/null differ
diff --git a/tactility-esp/assets/sdcard_mounted.png b/tactility-esp/assets/sdcard_mounted.png
deleted file mode 100644
index 472f12f7..00000000
Binary files a/tactility-esp/assets/sdcard_mounted.png and /dev/null differ
diff --git a/tactility-esp/assets/sdcard_unmounted.png b/tactility-esp/assets/sdcard_unmounted.png
deleted file mode 100644
index 27e9a151..00000000
Binary files a/tactility-esp/assets/sdcard_unmounted.png and /dev/null differ
diff --git a/tactility-esp/src/apps/system/wifi_manage/wifi_manage_view.c b/tactility-esp/src/apps/system/wifi_manage/wifi_manage_view.c
index 1d5270e4..063b15e4 100644
--- a/tactility-esp/src/apps/system/wifi_manage/wifi_manage_view.c
+++ b/tactility-esp/src/apps/system/wifi_manage/wifi_manage_view.c
@@ -26,30 +26,6 @@ static void on_disconnect_pressed(lv_event_t* event) {
// region Secondary updates
-static const char* get_network_icon(int8_t rssi, wifi_auth_mode_t auth_mode) {
- if (rssi > -67) {
- if (auth_mode == WIFI_AUTH_OPEN)
- return "A:/assets/network_wifi.png";
- else
- return "A:/assets/network_wifi_locked.png";
- } else if (rssi > -70) {
- if (auth_mode == WIFI_AUTH_OPEN)
- return "A:/assets/network_wifi_3_bar.png";
- else
- return "A:/assets/network_wifi_3_bar_locked.png";
- } else if (rssi > -80) {
- if (auth_mode == WIFI_AUTH_OPEN)
- return "A:/assets/network_wifi_2_bar.png";
- else
- return "A:/assets/network_wifi_2_bar_locked.png";
- } else {
- if (auth_mode == WIFI_AUTH_OPEN)
- return "A:/assets/network_wifi_1_bar.png";
- else
- return "A:/assets/network_wifi_1_bar_locked.png";
- }
-}
-
static void connect(lv_event_t* event) {
lv_obj_t* button = event->current_target;
// Assumes that the second child of the button is a label ... risky
@@ -64,7 +40,7 @@ static void connect(lv_event_t* event) {
static void create_network_button(WifiManageView* view, WifiManageBindings* bindings, WifiApRecord* record) {
const char* ssid = (const char*)record->ssid;
- const char* icon = get_network_icon(record->rssi, record->auth_mode);
+ const char* icon = wifi_get_status_icon_for_rssi(record->rssi, record->auth_mode != WIFI_AUTH_OPEN);
lv_obj_t* ap_button = lv_list_add_btn(
view->networks_list,
icon,
diff --git a/tactility-esp/src/services/wifi/wifi.c b/tactility-esp/src/services/wifi/wifi.c
index 45d57a8d..7984b5c9 100644
--- a/tactility-esp/src/services/wifi/wifi.c
+++ b/tactility-esp/src/services/wifi/wifi.c
@@ -1,5 +1,6 @@
#include "wifi.h"
+#include "assets.h"
#include "check.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
@@ -33,10 +34,12 @@ typedef struct {
uint16_t scan_list_limit;
int8_t statusbar_icon_id;
bool scan_active;
+ bool secure_connection;
esp_event_handler_instance_t event_handler_any_id;
esp_event_handler_instance_t event_handler_got_ip;
EventGroupHandle_t event_group;
WifiRadioState radio_state;
+ const char* _Nullable last_statusbar_icon;
} Wifi;
typedef enum {
@@ -86,7 +89,9 @@ static Wifi* wifi_alloc() {
instance->event_handler_got_ip = NULL;
instance->event_group = xEventGroupCreate();
instance->radio_state = WIFI_RADIO_OFF;
- instance->statusbar_icon_id = tt_statusbar_icon_add("A:/assets/ic_small_wifi_off.png");
+ instance->statusbar_icon_id = tt_statusbar_icon_add(TT_ASSETS_ICON_WIFI_OFF);
+ instance->last_statusbar_icon = NULL;
+ instance->secure_connection = false;
return instance;
}
@@ -225,35 +230,6 @@ static void wifi_scan_list_free_safely(Wifi* wifi) {
static void wifi_publish_event_simple(Wifi* wifi, WifiEventType type) {
WifiEvent turning_on_event = {.type = type};
- switch (type) {
- case WifiEventTypeRadioStateOn:
- break;
- case WifiEventTypeRadioStateOnPending:
- break;
- case WifiEventTypeRadioStateOff:
- tt_statusbar_icon_set_image(wifi->statusbar_icon_id, "A:/assets/ic_small_wifi_off.png");
- break;
- case WifiEventTypeRadioStateOffPending:
- break;
- case WifiEventTypeScanStarted:
- break;
- case WifiEventTypeScanFinished:
- break;
- case WifiEventTypeDisconnected:
- tt_statusbar_icon_set_image(wifi->statusbar_icon_id, "A:/assets/ic_small_wifi_off.png");
- break;
- case WifiEventTypeConnectionPending:
- tt_statusbar_icon_set_image(wifi->statusbar_icon_id, "A:/assets/network_wifi_1_bar.png");
- break;
- case WifiEventTypeConnectionSuccess:
- // TODO: update with actual bars
- tt_statusbar_icon_set_image(wifi->statusbar_icon_id, "A:/assets/network_wifi.png");
- break;
- case WifiEventTypeConnectionFailed:
- tt_statusbar_icon_set_image(wifi->statusbar_icon_id, "A:/assets/ic_small_wifi_off.png");
- break;
- }
-
tt_pubsub_publish(wifi->pubsub, &turning_on_event);
}
@@ -266,6 +242,8 @@ static void event_handler(TT_UNUSED void* arg, esp_event_base_t event_base, int3
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
xEventGroupSetBits(wifi_singleton->event_group, WIFI_FAIL_BIT);
TT_LOG_I(TAG, "event_handler: disconnected");
+ wifi_singleton->radio_state = WIFI_RADIO_ON;
+ wifi_publish_event_simple(wifi_singleton, WifiEventTypeDisconnected);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
TT_LOG_I(TAG, "event_handler: got ip:" IPSTR, IP2STR(&event->ip_info.ip));
@@ -444,6 +422,47 @@ static void wifi_scan_internal(Wifi* wifi) {
TT_LOG_I(TAG, "Finished scan");
}
+const char* wifi_get_status_icon_for_rssi(int rssi, bool secured) {
+ if (rssi > -67) {
+ return secured ? TT_ASSETS_ICON_WIFI_SIGNAL_4_LOCKED : TT_ASSETS_ICON_WIFI_SIGNAL_4;
+ } else if (rssi > -70) {
+ return secured ? TT_ASSETS_ICON_WIFI_SIGNAL_3_LOCKED : TT_ASSETS_ICON_WIFI_SIGNAL_3;
+ } else if (rssi > -80) {
+ return secured ? TT_ASSETS_ICON_WIFI_SIGNAL_2_LOCKED : TT_ASSETS_ICON_WIFI_SIGNAL_2;
+ } else {
+ return secured ? TT_ASSETS_ICON_WIFI_SIGNAL_1_LOCKED : TT_ASSETS_ICON_WIFI_SIGNAL_1;
+ }
+}
+
+static const char* wifi_get_status_icon(WifiRadioState state, bool secure) {
+ static int rssi = 0;
+ switch (state) {
+ case WIFI_RADIO_ON_PENDING:
+ case WIFI_RADIO_ON:
+ case WIFI_RADIO_OFF_PENDING:
+ case WIFI_RADIO_OFF:
+ return TT_ASSETS_ICON_WIFI_OFF;
+ case WIFI_RADIO_CONNECTION_PENDING:
+ return TT_ASSETS_ICON_WIFI_FIND;
+ case WIFI_RADIO_CONNECTION_ACTIVE:
+ if (esp_wifi_sta_get_rssi(&rssi) == ESP_OK) {
+ return wifi_get_status_icon_for_rssi(rssi, secure);
+ } else {
+ return secure ? TT_ASSETS_ICON_WIFI_SIGNAL_0_LOCKED : TT_ASSETS_ICON_WIFI_SIGNAL_0;
+ }
+ default:
+ tt_crash_implementation("not implemented");
+ }
+}
+
+static void wifi_update_statusbar(Wifi* wifi) {
+ const char* icon = wifi_get_status_icon(wifi->radio_state, wifi->secure_connection);
+ if (icon != wifi->last_statusbar_icon) {
+ tt_statusbar_icon_set_image(wifi->statusbar_icon_id, icon);
+ wifi->last_statusbar_icon = icon;
+ }
+}
+
static void wifi_connect_internal(Wifi* wifi, WifiConnectMessage* connect_message) {
// TODO: only when connected!
wifi_disconnect_internal(wifi);
@@ -467,6 +486,8 @@ static void wifi_connect_internal(Wifi* wifi, WifiConnectMessage* connect_messag
memcpy(wifi_config.sta.ssid, connect_message->ssid, 32);
memcpy(wifi_config.sta.password, connect_message->password, 64);
+ wifi->secure_connection = (wifi_config.sta.password[0] != 0x00);
+
esp_err_t set_config_result = esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
if (set_config_result != ESP_OK) {
wifi->radio_state = WIFI_RADIO_ON;
@@ -589,6 +610,8 @@ _Noreturn int32_t wifi_main(TT_UNUSED void* parameter) {
break;
}
}
+
+ wifi_update_statusbar(wifi);
}
}
diff --git a/tactility-esp/src/services/wifi/wifi.h b/tactility-esp/src/services/wifi/wifi.h
index 76794445..4d543685 100644
--- a/tactility-esp/src/services/wifi/wifi.h
+++ b/tactility-esp/src/services/wifi/wifi.h
@@ -62,6 +62,9 @@ WifiRadioState wifi_get_radio_state();
*/
void wifi_scan();
+/**
+ * @return true if wifi is actively scanning
+ */
bool wifi_is_scanning();
/**
@@ -96,6 +99,14 @@ void wifi_connect(const char* ssid, const char _Nullable password[64]);
*/
void wifi_disconnect();
+/**
+ * Return the relevant icon asset from assets.h for the given inputs
+ * @param rssi the rssi value
+ * @param secured whether the access point is a secured one (as in: not an open one)
+ * @return
+ */
+const char* wifi_get_status_icon_for_rssi(int rssi, bool secured);
+
#ifdef __cplusplus
}
#endif
diff --git a/tactility/src/app.c b/tactility/src/app.c
index 25a3858b..b9370cbc 100644
--- a/tactility/src/app.c
+++ b/tactility/src/app.c
@@ -1,7 +1,10 @@
#include "app_i.h"
+#include "log.h"
#include
+#define TAG "app"
+
static AppFlags tt_app_get_flags_default(AppType type);
static const AppFlags DEFAULT_FLAGS = {
@@ -11,6 +14,11 @@ static const AppFlags DEFAULT_FLAGS = {
// region Alloc/free
App tt_app_alloc(const AppManifest* manifest, Bundle* _Nullable parameters) {
+#ifdef ESP_PLATFORM
+ size_t memory_before = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
+#else
+ size_t memory_before = 0;
+#endif
AppData* data = malloc(sizeof(AppData));
*data = (AppData) {
.mutex = tt_mutex_alloc(MutexTypeNormal),
@@ -18,6 +26,7 @@ App tt_app_alloc(const AppManifest* manifest, Bundle* _Nullable parameters) {
.flags = tt_app_get_flags_default(manifest->type),
.manifest = manifest,
.parameters = parameters,
+ .memory = memory_before,
.data = NULL
};
return (App*)data;
@@ -25,11 +34,25 @@ App tt_app_alloc(const AppManifest* manifest, Bundle* _Nullable parameters) {
void tt_app_free(App app) {
AppData* data = (AppData*)app;
+
+ size_t memory_before = data->memory;
+
if (data->parameters) {
tt_bundle_free(data->parameters);
}
tt_mutex_free(data->mutex);
free(data);
+
+#ifdef ESP_PLATFORM
+ size_t memory_after = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
+#else
+ size_t memory_after = 0;
+#endif
+
+ if (memory_after < memory_before) {
+ TT_LOG_W(TAG, "Potential memory leak: gained %u bytes after closing app", memory_before - memory_after);
+ TT_LOG_W(TAG, "Note that WiFi service frees up memory asynchronously and that the leak can be caused by an app that was launched by this app.");
+ }
}
// endregion
diff --git a/tactility/src/app_i.h b/tactility/src/app_i.h
index 97573586..d64a9e98 100644
--- a/tactility/src/app_i.h
+++ b/tactility/src/app_i.h
@@ -14,6 +14,8 @@ typedef struct {
Mutex mutex;
const AppManifest* manifest;
AppState state;
+ /** @brief Memory marker at start of app, to detect memory leaks */
+ size_t memory;
AppFlags flags;
/** @brief Optional parameters to start the app with
* When these are stored in the app struct, the struct takes ownership.
diff --git a/tactility/src/assets.h b/tactility/src/assets.h
new file mode 100644
index 00000000..2d7c9605
--- /dev/null
+++ b/tactility/src/assets.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#define TT_ASSET_FOLDER "A:/assets/"
+#define TT_ASSET(file) TT_ASSET_FOLDER file
+
+#define TT_ASSETS_ICON_SDCARD TT_ASSET("sdcard.png")
+#define TT_ASSETS_ICON_SDCARD_ALERT TT_ASSET("sdcard_alert.png")
+
+#define TT_ASSETS_ICON_WIFI_CONNECTION_ISSUE TT_ASSET("wifi_connection_issue.png")
+#define TT_ASSETS_ICON_WIFI_FIND TT_ASSET("wifi_find.png")
+#define TT_ASSETS_ICON_WIFI_OFF TT_ASSET("wifi_off.png")
+#define TT_ASSETS_ICON_WIFI_PERM_SCAN TT_ASSET("wifi_perm_scan.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_0 TT_ASSET("wifi_signal_0.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_0_LOCKED TT_ASSET("wifi_signal_0_locked.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_1 TT_ASSET("wifi_signal_1.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_1_LOCKED TT_ASSET("wifi_signal_1_locked.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_2 TT_ASSET("wifi_signal_2.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_2_LOCKED TT_ASSET("wifi_signal_2_locked.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_3 TT_ASSET("wifi_signal_3.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_3_LOCKED TT_ASSET("wifi_signal_3_locked.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_4 TT_ASSET("wifi_signal_4.png")
+#define TT_ASSETS_ICON_WIFI_SIGNAL_4_LOCKED TT_ASSET("wifi_signal_4_locked.png")
diff --git a/tactility/src/hardware.c b/tactility/src/hardware.c
index 15ff0931..7d1fa4e6 100644
--- a/tactility/src/hardware.c
+++ b/tactility/src/hardware.c
@@ -1,4 +1,5 @@
#include "hardware_i.h"
+#include "sdcard_i.h"
#define TAG "hardware"
@@ -12,6 +13,7 @@ void tt_hardware_init(const HardwareConfig* config) {
tt_check(config->bootstrap(), "bootstrap failed");
}
+ tt_sdcard_init();
if (config->sdcard != NULL) {
TT_LOG_I(TAG, "Mounting sdcard");
tt_sdcard_mount(config->sdcard);
diff --git a/tactility/src/sdcard.c b/tactility/src/sdcard.c
index 3bf5eca4..b04a86e3 100644
--- a/tactility/src/sdcard.c
+++ b/tactility/src/sdcard.c
@@ -2,12 +2,10 @@
#include "mutex.h"
#include "tactility_core.h"
-#include "ui/statusbar.h"
#define TAG "sdcard"
-static Mutex* mutex = NULL;
-static int8_t statusbar_icon = -1;
+static Mutex mutex = NULL;
typedef struct {
const SdCard* sdcard;
@@ -19,15 +17,13 @@ static MountData data = {
.context = NULL
};
-static void sdcard_ensure_initialized() {
+void tt_sdcard_init() {
if (mutex == NULL) {
mutex = tt_mutex_alloc(MutexTypeRecursive);
- statusbar_icon = tt_statusbar_icon_add("A:/assets/sdcard_unmounted.png");
}
}
static bool sdcard_lock(uint32_t timeout_ticks) {
- sdcard_ensure_initialized();
return tt_mutex_acquire(mutex, timeout_ticks) == TtStatusOk;
}
@@ -51,7 +47,6 @@ bool tt_sdcard_mount(const SdCard* sdcard) {
};
sdcard_unlock();
if (data.context != NULL) {
- tt_statusbar_icon_set_image(statusbar_icon, "A:/assets/sdcard_mounted.png");
return true;
} else {
return false;
@@ -62,8 +57,19 @@ bool tt_sdcard_mount(const SdCard* sdcard) {
}
}
-bool tt_sdcard_is_mounted() {
- return data.context != NULL;
+SdcardState tt_sdcard_get_state() {
+ if (data.context == NULL) {
+ return SDCARD_STATE_UNMOUNTED;
+ } else {
+ // TODO: Side-effects are not great - consider refactoring this, so:
+ // Consider making tt_sdcard_get_status() that can return an error state
+ // The sdcard service can then auto-dismount
+ if (data.sdcard->is_mounted(data.context)) {
+ return SDCARD_STATE_MOUNTED;
+ } else {
+ return SDCARD_STATE_ERROR;
+ }
+ }
}
bool tt_sdcard_unmount(uint32_t timeout_ticks) {
@@ -78,7 +84,6 @@ bool tt_sdcard_unmount(uint32_t timeout_ticks) {
.sdcard = NULL
};
result = true;
- tt_statusbar_icon_set_image(statusbar_icon, "A:/assets/sdcard_unmounted.png");
} else {
TT_LOG_E(TAG, "Can't unmount: nothing mounted");
}
diff --git a/tactility/src/sdcard.h b/tactility/src/sdcard.h
index 9a9de7f6..afd1a1bd 100644
--- a/tactility/src/sdcard.h
+++ b/tactility/src/sdcard.h
@@ -9,7 +9,14 @@ extern "C" {
#endif
typedef void* (*SdcardMount)(const char* mount_path);
-typedef void (*SdcardUnmount)(void*);
+typedef void (*SdcardUnmount)(void* context);
+typedef bool (*SdcardIsMounted)(void* context);
+
+typedef enum {
+ SDCARD_STATE_MOUNTED,
+ SDCARD_STATE_UNMOUNTED,
+ SDCARD_STATE_ERROR,
+} SdcardState;
typedef enum {
SDCARD_MOUNT_BEHAVIOUR_AT_BOOT, /** Only mount at boot */
@@ -19,11 +26,12 @@ typedef enum {
typedef struct {
SdcardMount mount;
SdcardUnmount unmount;
+ SdcardIsMounted is_mounted;
SdcardMountBehaviour mount_behaviour;
} SdCard;
bool tt_sdcard_mount(const SdCard* sdcard);
-bool tt_sdcard_is_mounted();
+SdcardState tt_sdcard_get_state();
bool tt_sdcard_unmount();
#ifdef __cplusplus
diff --git a/tactility/src/sdcard_i.h b/tactility/src/sdcard_i.h
new file mode 100644
index 00000000..ce953c00
--- /dev/null
+++ b/tactility/src/sdcard_i.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void tt_sdcard_init();
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/tactility/src/services/sdcard/sdcard.c b/tactility/src/services/sdcard/sdcard.c
new file mode 100644
index 00000000..9aadf0dd
--- /dev/null
+++ b/tactility/src/services/sdcard/sdcard.c
@@ -0,0 +1,117 @@
+#include
+
+#include "assets.h"
+#include "mutex.h"
+#include "service.h"
+#include "tactility.h"
+#include "tactility_core.h"
+#include "ui/statusbar.h"
+
+#define TAG "sdcard_service"
+
+static int32_t sdcard_task(TT_UNUSED void* context);
+
+typedef struct {
+ Mutex mutex;
+ Thread* thread;
+ SdcardState last_state;
+ int8_t statusbar_icon_id;
+ bool interrupted;
+} ServiceData;
+
+static ServiceData* service_data_alloc() {
+ ServiceData* data = malloc(sizeof(ServiceData));
+ *data = (ServiceData) {
+ .mutex = tt_mutex_alloc(MutexTypeNormal),
+ .thread = tt_thread_alloc_ex(
+ "sdcard",
+ 3000, // Minimum is ~2800 @ ESP-IDF 5.1.2 when ejecting sdcard
+ &sdcard_task,
+ data
+ ),
+ .last_state = -1,
+ .statusbar_icon_id = tt_statusbar_icon_add(NULL),
+ .interrupted = false
+ };
+ return data;
+}
+
+static void service_data_free(ServiceData* data) {
+ tt_mutex_free(data->mutex);
+ tt_statusbar_icon_remove(data->statusbar_icon_id);
+ tt_thread_free(data->thread);
+}
+
+static void service_data_lock(ServiceData* data) {
+ tt_check(tt_mutex_acquire(data->mutex, TtWaitForever) == TtStatusOk);
+}
+
+static void service_data_unlock(ServiceData* data) {
+ tt_check(tt_mutex_release(data->mutex) == TtStatusOk);
+}
+
+static int32_t sdcard_task(void* context) {
+ ServiceData* data = (ServiceData*)context;
+
+ bool interrupted = false;
+
+ // We set NULL as statusbar image by default, so it's hidden by default
+ tt_statusbar_icon_set_visibility(data->statusbar_icon_id, true);
+
+ do {
+ service_data_lock(data);
+
+ interrupted = data->interrupted;
+
+ SdcardState new_state = tt_sdcard_get_state();
+
+ if (new_state == SDCARD_STATE_ERROR) {
+ TT_LOG_W(TAG, "Sdcard error - unmounting. Did you eject the card in an unsafe manner?");
+ tt_sdcard_unmount();
+ }
+
+ if (new_state != data->last_state) {
+ TT_LOG_I(TAG, "State change %d -> %d", data->last_state, new_state);
+ if (new_state == SDCARD_STATE_MOUNTED) {
+ tt_statusbar_icon_set_image(data->statusbar_icon_id, TT_ASSETS_ICON_SDCARD);
+ } else {
+ tt_statusbar_icon_set_image(data->statusbar_icon_id, TT_ASSETS_ICON_SDCARD_ALERT);
+ }
+ data->last_state = new_state;
+ }
+
+ service_data_unlock(data);
+ tt_delay_ms(2000);
+ } while (!interrupted);
+
+ return 0;
+}
+
+static void on_start(Service service) {
+ if (tt_get_config()->hardware->sdcard != NULL) {
+ ServiceData* data = service_data_alloc();
+ tt_service_set_data(service, data);
+ tt_thread_start(data->thread);
+ } else {
+ TT_LOG_I(TAG, "task not started due to config");
+ }
+}
+
+static void on_stop(Service service) {
+ ServiceData* data = tt_service_get_data(service);
+ if (data != NULL) {
+ service_data_lock(data);
+ data->interrupted = true;
+ service_data_unlock(data);
+
+ tt_thread_join(data->thread);
+
+ service_data_free(data);
+ }
+}
+
+const ServiceManifest sdcard_service = {
+ .id = "sdcard",
+ .on_start = &on_start,
+ .on_stop = &on_stop
+};
diff --git a/tactility/src/tactility.c b/tactility/src/tactility.c
index 4123ebb7..581b2924 100644
--- a/tactility/src/tactility.c
+++ b/tactility/src/tactility.c
@@ -14,10 +14,12 @@ static const Config* config_instance = NULL;
extern const ServiceManifest gui_service;
extern const ServiceManifest loader_service;
+extern const ServiceManifest sdcard_service;
static const ServiceManifest* const system_services[] = {
&gui_service,
- &loader_service // depends on gui service
+ &loader_service, // depends on gui service
+ &sdcard_service
};
// endregion
@@ -87,6 +89,9 @@ static void register_and_start_user_services(const ServiceManifest* const servic
TT_UNUSED void tt_init(const Config* config) {
TT_LOG_I(TAG, "tt_init started");
+ // Assign early so starting services can use it
+ config_instance = config;
+
tt_service_registry_init();
tt_app_manifest_registry_init();
@@ -122,8 +127,6 @@ TT_UNUSED void tt_init(const Config* config) {
}
TT_LOG_I(TAG, "tt_init complete");
-
- config_instance = config;
}
const Config* _Nullable tt_get_config() {
diff --git a/tactility/src/ui/statusbar.c b/tactility/src/ui/statusbar.c
index a84d2e08..1506dda8 100644
--- a/tactility/src/ui/statusbar.c
+++ b/tactility/src/ui/statusbar.c
@@ -18,7 +18,7 @@ typedef struct {
} StatusbarIcon;
typedef struct {
- Mutex* mutex;
+ Mutex mutex;
PubSub* pubsub;
StatusbarIcon icons[STATUSBAR_ICON_LIMIT];
} StatusbarData;
@@ -166,13 +166,13 @@ static void statusbar_event(TT_UNUSED const lv_obj_class_t* class_p, lv_event_t*
}
}
-int8_t tt_statusbar_icon_add(const char* image) {
+int8_t tt_statusbar_icon_add(const char* _Nullable image) {
statusbar_lock();
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 = true;
+ statusbar_data.icons[i].visible = (image != NULL);
statusbar_data.icons[i].image = image;
result = i;
TT_LOG_I(TAG, "id %d: added", i);
diff --git a/tactility/src/ui/statusbar.h b/tactility/src/ui/statusbar.h
index 73350a7e..4b4f9a67 100644
--- a/tactility/src/ui/statusbar.h
+++ b/tactility/src/ui/statusbar.h
@@ -12,7 +12,7 @@ extern "C" {
#define STATUSBAR_HEIGHT (STATUSBAR_ICON_SIZE + 4) // 4 extra pixels for border and outline
lv_obj_t* tt_statusbar_create(lv_obj_t* parent);
-int8_t tt_statusbar_icon_add(const char* image);
+int8_t tt_statusbar_icon_add(const char* _Nullable image);
void tt_statusbar_icon_remove(int8_t id);
void tt_statusbar_icon_set_image(int8_t id, const char* image);
void tt_statusbar_icon_set_visibility(int8_t id, bool visible);