From 63426aaab37e6aa2781bcd1110afef377d5a51e2 Mon Sep 17 00:00:00 2001 From: Yehuda E Date: Thu, 18 Sep 2025 19:12:38 +0300 Subject: [PATCH 1/2] prj.conf: Disable i2c logs Disable i2c logs. Signed-off-by: Yehuda E --- prj.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prj.conf b/prj.conf index fe82aec..3ae00c2 100644 --- a/prj.conf +++ b/prj.conf @@ -63,6 +63,7 @@ CONFIG_SYSTEM_WORKQUEUE_PRIORITY=-1 # Input Subsystem Configuration - Disable input warnings CONFIG_INPUT=y CONFIG_INPUT_LOG_LEVEL_OFF=y +CONFIG_I2C_LOG_LEVEL_OFF=y # Flash Configurations CONFIG_FLASH=y @@ -73,4 +74,4 @@ CONFIG_NVS=y CONFIG_COUNTER=y # Watchdog Timer -CONFIG_WATCHDOG=y \ No newline at end of file +CONFIG_WATCHDOG=y From 496ad4845f07604b02369eb916a0cb5940488cdb Mon Sep 17 00:00:00 2001 From: Yehuda E Date: Sun, 21 Sep 2025 13:53:25 +0300 Subject: [PATCH 2/2] Zephyr-Watch: #10 Add settings screen - Implement settings screen - Change brightness - Enable / Disbale BLE Signed-off-by: Yehuda E --- prj.conf | 2 +- src/bluetooth/infrastructure.c | 57 +++++--- src/bluetooth/infrastructure.h | 10 +- src/display/display.c | 45 +++++- src/userinterface/screens/menu/menu.c | 75 ++++++---- src/userinterface/screens/menu/menu.h | 12 +- src/userinterface/screens/settings/settings.c | 137 ++++++++++++++++++ src/userinterface/screens/settings/settings.h | 30 ++++ 8 files changed, 303 insertions(+), 65 deletions(-) create mode 100644 src/userinterface/screens/settings/settings.c create mode 100644 src/userinterface/screens/settings/settings.h diff --git a/prj.conf b/prj.conf index 3ae00c2..1a78d8c 100644 --- a/prj.conf +++ b/prj.conf @@ -19,7 +19,7 @@ CONFIG_LV_FONT_MONTSERRAT_16=y # Important for LVGL to work. CONFIG_MAIN_STACK_SIZE=8192 # CONFIG_LV_MEM_CUSTOM=y -CONFIG_LV_Z_MEM_POOL_SIZE=16384 +CONFIG_LV_Z_MEM_POOL_SIZE=32768 # PWM Configurations CONFIG_PWM=y diff --git a/src/bluetooth/infrastructure.c b/src/bluetooth/infrastructure.c index 0241d4d..192903d 100644 --- a/src/bluetooth/infrastructure.c +++ b/src/bluetooth/infrastructure.c @@ -2,14 +2,14 @@ * This file manages Bluetooth functionality, including advertising and connection handling. * * @license: GNU v3 - * @maintainer: electricalgorithm @ github + * @maintainer: electricalgorithm @ github */ #include "userinterface/screens/blepairing/blepairing.h" #include "zephyr/bluetooth/conn.h" -#include #include #include +#include LOG_MODULE_REGISTER(ZephyrWatch_BLE, LOG_LEVEL_INF); @@ -22,7 +22,8 @@ static const struct bt_data m_sd[] = { BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), }; -static void start_advertisement() { +static void start_advertisement() +{ const int err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, m_ad, ARRAY_SIZE(m_ad), m_sd, ARRAY_SIZE(m_sd)); if (err) { LOG_DBG("Advertising failed to start (err %d).", err); @@ -31,8 +32,10 @@ static void start_advertisement() { LOG_DBG("Advertising successfully started."); } -static void process_connection(struct bt_conn *conn, uint8_t err) { - if (err) LOG_ERR("Connection failed (err %u).", err); +static void process_connection(struct bt_conn* conn, uint8_t err) +{ + if (err) + LOG_ERR("Connection failed (err %u).", err); else { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); @@ -40,7 +43,8 @@ static void process_connection(struct bt_conn *conn, uint8_t err) { } } -static void process_disconnection(struct bt_conn *conn, uint8_t reason) { +static void process_disconnection(struct bt_conn* conn, uint8_t reason) +{ LOG_INF("Disconnected (reason 0x%02x).", reason); } @@ -50,14 +54,16 @@ BT_CONN_CB_DEFINE(connection_callbacks) = { .recycled = start_advertisement, }; -char* passkey_to_string(const unsigned int passkey) { +char* passkey_to_string(const unsigned int passkey) +{ static char passkey_str[7]; snprintf(passkey_str, sizeof(passkey_str), "%06u", passkey); return passkey_str; } -static void process_passkey_display(struct bt_conn *conn, unsigned int passkey){ - char addr[BT_ADDR_LE_STR_LEN] = {0}; +static void process_passkey_display(struct bt_conn* conn, unsigned int passkey) +{ + char addr[BT_ADDR_LE_STR_LEN] = { 0 }; // Write PIN to the screen. blepairing_screen_init(); blepairing_screen_set_pin(passkey_to_string(passkey)); @@ -68,19 +74,22 @@ static void process_passkey_display(struct bt_conn *conn, unsigned int passkey){ LOG_DBG("Passkey for %s: %06u", addr, passkey); } -static void process_auth_cancel(struct bt_conn *conn){ +static void process_auth_cancel(struct bt_conn* conn) +{ char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_DBG("Pairing cancelled: %s", addr); blepairing_screen_unload(); } -static void process_pairing_complete(struct bt_conn *conn, bool bonded) { +static void process_pairing_complete(struct bt_conn* conn, bool bonded) +{ LOG_DBG("Pairing complete. Bonded: %s", bonded ? "OK" : "FAILURE"); blepairing_screen_unload(); } -static void process_pairing_failed(struct bt_conn *conn, enum bt_security_err reason) { +static void process_pairing_failed(struct bt_conn* conn, enum bt_security_err reason) +{ LOG_DBG("Pairing failed. Reason: 0x%02x", reason); bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL); blepairing_screen_unload(); @@ -98,7 +107,8 @@ static struct bt_conn_auth_cb auth_callbacks = { }; /* The API function to enable Bluetooth and start advertisement. */ -uint8_t enable_bluetooth_subsystem() { +int enable_bluetooth_subsystem() +{ int err; err = bt_enable(NULL); @@ -136,21 +146,30 @@ uint8_t enable_bluetooth_subsystem() { return 0; } -uint8_t disable_bluetooth_subsystem() { +int disable_bluetooth_subsystem() +{ int err; err = bt_le_adv_stop(); if (err) { - LOG_ERR("Advertising failed to stop (err %d).", err); + LOG_ERR("Failed to stop advertising (err %d).", err); + return err; + } + LOG_DBG("Advertising stopped successfully."); + + err = bt_conn_auth_info_cb_unregister(&auth_info_callbacks); + if (err) { + LOG_ERR("Failed to unregister authentication information callbacks (err %d).", err); return err; } - LOG_DBG("Advertising successfully stopped."); + LOG_DBG("Authentication information callback unregistered successfully."); err = bt_disable(); if (err) { - LOG_ERR("Bluetooth failed to disable (err %d).", err); + LOG_ERR("Failed to disable Bluetooth subsystem (err %d).", err); return err; } - LOG_DBG("Bluetooth disabled."); + LOG_DBG("Bluetooth subsystem disabled successfully."); + return 0; -} \ No newline at end of file +} diff --git a/src/bluetooth/infrastructure.h b/src/bluetooth/infrastructure.h index 385d9de..81be364 100644 --- a/src/bluetooth/infrastructure.h +++ b/src/bluetooth/infrastructure.h @@ -2,7 +2,7 @@ * This interface manages Bluetooth functionality, including advertising and connection handling. * * @license: GNU v3 - * @maintainer: electricalgorithm @ github + * @maintainer: electricalgorithm @ github */ #ifndef BLUETOOTH_INFRASTRUCTURE_H_ @@ -12,15 +12,15 @@ extern "C" { #endif -#include #include #include +#include -uint8_t enable_bluetooth_subsystem(); -uint8_t disable_bluetooth_subsystem(); +int enable_bluetooth_subsystem(); +int disable_bluetooth_subsystem(); #ifdef __cplusplus } #endif -#endif /* BLUETOOTH_INFRASTRUCTURE_H_ */ \ No newline at end of file +#endif /* BLUETOOTH_INFRASTRUCTURE_H_ */ diff --git a/src/display/display.c b/src/display/display.c index 5fb937a..ca41f4f 100644 --- a/src/display/display.c +++ b/src/display/display.c @@ -20,10 +20,11 @@ LOG_MODULE_REGISTER(ZephyrWatch_Display, LOG_LEVEL_INF); /* ENABLE_DISPLAY_SUBSYSTEM * Set the Zephyr display device and set backlight. */ -int enable_display_subsystem() { +int enable_display_subsystem() +{ int ret; - const struct device *display_dev = DEVICE_DT_GET(DISPLAY_DEVICE); + const struct device* display_dev = DEVICE_DT_GET(DISPLAY_DEVICE); ret = device_is_ready(display_dev); if (!ret) { LOG_ERR("Display device is not ready, exiting... (RET: %d)", ret); @@ -56,11 +57,11 @@ int enable_display_subsystem() { return 0; } - /* ENABLE_DISPLAY_SUBSYSTEM * Disable the Zephyr display device and set backlight to 0. */ -int disable_display_subsystem() { +int disable_display_subsystem() +{ LOG_DBG("Not implemented yet."); return 0; } @@ -68,7 +69,37 @@ int disable_display_subsystem() { /* CHANGE_BRIGHTNESS * Change the brightness based on a percentage. */ -int change_brightness(uint8_t perc) { - LOG_DBG("Not implemented yet."); +int change_brightness(uint8_t perc) +{ + int ret; + const struct pwm_dt_spec backlight = PWM_DT_SPEC_GET_BY_IDX(DISPLAY_PWM_DEVICE, 0); + + // Check if PWM is ready + if (!pwm_is_ready_dt(&backlight)) { + LOG_ERR("PWM device is not ready"); + return -ENODEV; + } + LOG_DBG("PWM device is ready"); + + // Clamp percentage to max 100% and min 5% + if (perc > 100) + perc = 100; + if (perc < 5) + perc = 5; + + // Define a PWM period (in nanoseconds). For example, 20 kHz = 50 us = 50000 ns + uint32_t period_ns = 50000; + + // Calculate pulse width (duty cycle) from percentage + uint32_t pulse_ns = (period_ns * perc) / 100; + + // Set the PWM signal + ret = pwm_set_dt(&backlight, period_ns, pulse_ns); + if (ret < 0) { + LOG_ERR("Failed to set PWM (ret = %d)", ret); + return ret; + } + + LOG_DBG("Brightness set to %d%%", perc); return 0; -} \ No newline at end of file +} diff --git a/src/userinterface/screens/menu/menu.c b/src/userinterface/screens/menu/menu.c index 80688e7..516a760 100644 --- a/src/userinterface/screens/menu/menu.c +++ b/src/userinterface/screens/menu/menu.c @@ -5,13 +5,16 @@ * @maintainer electricalgorithm @ github */ - #include #include "lvgl.h" +#include +#include #include "misc/lv_event.h" +#include "userinterface/screens/home/home.h" +#include "userinterface/screens/menu/menu.h" +#include "userinterface/screens/settings/settings.h" #include "userinterface/userinterface.h" #include "userinterface/utils.h" -#include "userinterface/screens/home/home.h" // Define the maximum number of applications allowed. #define MAX_APPLICATIONS 10 @@ -21,8 +24,9 @@ LOG_MODULE_REGISTER(ZephyrWatch_UI_Menu, LOG_LEVEL_INF); // Structure to hold application information typedef struct { - lv_obj_t *screen; - char *name; + lv_obj_t** screen; + init_fn_t init_fn; + char* name; bool is_registered; } application_t; @@ -31,8 +35,8 @@ static application_t applications[MAX_APPLICATIONS]; static uint8_t application_count = 0; // The screen container. -lv_obj_t *menu_screen; -static lv_obj_t *menu_list; +lv_obj_t* menu_screen; +static lv_obj_t* menu_list; /** * Register an application to be displayed in the menu @@ -40,13 +44,15 @@ static lv_obj_t *menu_list; * @param name The name of the application to display * @return 0 on success, -1 if maximum applications reached */ -int register_application(lv_obj_t *screen, char *name) { +int register_application(lv_obj_t** screen, init_fn_t init_fn, char* name) +{ if (application_count >= MAX_APPLICATIONS) { LOG_ERR("Maximum number of applications reached."); return -1; // Maximum applications reached } applications[application_count].screen = screen; + applications[application_count].init_fn = init_fn; applications[application_count].name = name; applications[application_count].is_registered = true; application_count++; @@ -57,11 +63,12 @@ int register_application(lv_obj_t *screen, char *name) { /* MENU_SCREEN_EVENT * Event handler for menu screen gestures. It is used to detect non-list events. */ -void menu_screen_event(lv_event_t * event) { +void menu_screen_event(lv_event_t* event) +{ lv_event_code_t event_code = lv_event_get_code(event); // If double clicked, return to home with slide back effect.. if (event_code == LV_EVENT_DOUBLE_CLICKED) { - // Home screen is never deleted, but check it for any case. + // Home screen is never deleted, but check it for any case. if (!lv_obj_is_valid(home_screen)) { home_screen_init(); } @@ -74,18 +81,25 @@ void menu_screen_event(lv_event_t * event) { /* MENU_ITEM_EVENT_HANDLER * Event handler for menu item clicks. It is the main logic where we start screens. */ -static void menu_item_event_handler(lv_event_t *event) { +static void menu_item_event_handler(lv_event_t* event) +{ lv_event_code_t code = lv_event_get_code(event); LOG_DBG("Menu-Items - Event code: %d", code); if (code == LV_EVENT_CLICKED) { - uint8_t *app_index = (uint8_t*)lv_event_get_user_data(event); + uint8_t* app_index = (uint8_t*)lv_event_get_user_data(event); LOG_DBG("Clicked app index: %u", *app_index); - if (*app_index < application_count && applications[*app_index].screen != NULL) { - // Switch to the selected application screen - LOG_DBG("Switching to application: %s", applications[*app_index].name); - lv_screen_load(applications[*app_index].screen); + if (*app_index < application_count) { + if (applications[*app_index].init_fn != NULL && !lv_obj_is_valid(*applications[*app_index].screen)) { + applications[*app_index].init_fn(); + } + + if (lv_obj_is_valid(*applications[*app_index].screen)) { + // Switch to the selected application screen + LOG_DBG("Switching to application: %s", applications[*app_index].name); + lv_screen_load_anim(*applications[*app_index].screen, LV_SCR_LOAD_ANIM_MOVE_LEFT, 300, 0, false); + } } } } @@ -94,9 +108,10 @@ static void menu_item_event_handler(lv_event_t *event) { * Create one menu item in a list. Each menu item corresponds to an application and presented * as buttons. */ -static void create_menu_item(lv_obj_t *parent, const char *app_name, uint32_t app_index) { +static void create_menu_item(lv_obj_t* parent, const char* app_name, uint32_t app_index) +{ // Create a button for the menu item - lv_obj_t *btn = lv_button_create(parent); + lv_obj_t* btn = lv_button_create(parent); lv_obj_set_width(btn, lv_pct(95)); lv_obj_set_height(btn, 45); @@ -113,7 +128,7 @@ static void create_menu_item(lv_obj_t *parent, const char *app_name, uint32_t ap lv_obj_set_style_bg_color(btn, lv_color_hex(0x404040), LV_PART_MAIN | LV_STATE_PRESSED); // Create label for the button - lv_obj_t *label = lv_label_create(btn); + lv_obj_t* label = lv_label_create(btn); lv_label_set_text(label, app_name); lv_obj_set_style_text_color(label, lv_color_white(), LV_PART_MAIN); lv_obj_set_style_text_font(label, &lv_font_montserrat_14, LV_PART_MAIN); @@ -129,7 +144,8 @@ static void create_menu_item(lv_obj_t *parent, const char *app_name, uint32_t ap /* RENDER_MENU_ITEMS * Render all registered applications as menu items. */ -static void render_menu_items() { +static void render_menu_items() +{ for (uint8_t i = 0; i < application_count; i++) { if (applications[i].is_registered) { create_menu_item(menu_list, applications[i].name, i); @@ -137,19 +153,20 @@ static void render_menu_items() { } } -/* MENU_SCREEN_INIT +/* MENU_SCREEN_INIT * Create the menu screen using LVGL definitions. */ -void menu_screen_init() { +void menu_screen_init() +{ // Create the screen object which is the LV object with no parent. menu_screen = create_screen(); - + // Create a vertical flex layout container centered in the screen. - lv_obj_t *main_column = create_column(menu_screen, 100, 100); + lv_obj_t* main_column = create_column(menu_screen, 100, 100); // Create a title row - lv_obj_t *title_row = create_row(main_column, 100, 15); - lv_obj_t *title_label = lv_label_create(title_row); + lv_obj_t* title_row = create_row(main_column, 100, 15); + lv_obj_t* title_label = lv_label_create(title_row); lv_label_set_text(title_label, "Menu"); lv_obj_set_style_text_color(title_label, lv_color_white(), LV_PART_MAIN); lv_obj_set_style_text_font(title_label, &lv_font_montserrat_18, LV_PART_MAIN); @@ -175,10 +192,10 @@ void menu_screen_init() { lv_obj_set_flex_align(menu_list, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); // Register some example applications - register_application(NULL, "Settings"); - register_application(NULL, "Stopwatch"); - register_application(NULL, "Weather"); - register_application(NULL, "Music"); + register_application(&settings_screen, settings_screen_init, "Settings"); + register_application(NULL, NULL, "Stopwatch"); + register_application(NULL, NULL, "Weather"); + register_application(NULL, NULL, "Music"); // Render all registered applications render_menu_items(); diff --git a/src/userinterface/screens/menu/menu.h b/src/userinterface/screens/menu/menu.h index c66d97b..fd106d3 100644 --- a/src/userinterface/screens/menu/menu.h +++ b/src/userinterface/screens/menu/menu.h @@ -14,25 +14,29 @@ extern "C" { #include "lvgl.h" +/* Screen init function typedef */ +typedef void (*init_fn_t)(void); + /* The screen object to be used in the userinterface. */ -extern lv_obj_t *menu_screen; +extern lv_obj_t* menu_screen; /* The init implementation for the menu screen. */ void menu_screen_init(); /* Event handler for menu screen gestures. It is used to detect non-list events. */ -void menu_screen_event(lv_event_t * event); +void menu_screen_event(lv_event_t* event); /** * Register an application to be displayed in the menu * @param screen The screen object for the application + * @param init_fn The init function of the screen * @param name The name of the application to display * @return 0 on success, -1 if maximum applications reached */ -int register_application(lv_obj_t *screen, char *name); +int register_application(lv_obj_t** screen, init_fn_t init_fn, char* name); #ifdef __cplusplus } // extern "C" #endif -#endif \ No newline at end of file +#endif diff --git a/src/userinterface/screens/settings/settings.c b/src/userinterface/screens/settings/settings.c new file mode 100644 index 0000000..eef8f92 --- /dev/null +++ b/src/userinterface/screens/settings/settings.c @@ -0,0 +1,137 @@ +/** Settings Screen Implementation. + * Provides functionality to construct a settings screen using LVGL. + * + * @license GNU v3 + * @maintainer YehudaEi @ github + */ + +#include "lvgl.h" +#include + +#include "bluetooth/infrastructure.h" +#include "display/display.h" +#include "misc/lv_event.h" +#include "userinterface/screens/menu/menu.h" +#include "userinterface/userinterface.h" +#include "userinterface/utils.h" + +// Define the maximum number of applications allowed. +#define MAX_APPLICATIONS 10 + +// Create a logger. +LOG_MODULE_REGISTER(ZephyrWatch_UI_Settings, LOG_LEVEL_INF); + +// The screen container. +lv_obj_t* settings_screen; +static lv_obj_t* slider_brightness; +static lv_obj_t* enable_ble; + +/* SETTINGS_SCREEN_EVENT + * Event handler for menu screen gestures. It is used to detect non-list events. + */ +void settings_screen_event(lv_event_t* event) +{ + lv_event_code_t event_code = lv_event_get_code(event); + + // If double clicked, return to home with slide back effect.. + if (event_code == LV_EVENT_DOUBLE_CLICKED) { + // Home screen is never deleted, but check it for any case. + if (!lv_obj_is_valid(menu_screen)) { + menu_screen_init(); + } + // Go back to home screen with slide down animation. + // Do not delete the screen since register_application will generate new items. + lv_screen_load_anim(menu_screen, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 300, 0, false); + } +} + +void brightness_slider_event(lv_event_t* event) +{ + lv_event_code_t event_code = lv_event_get_code(event); + + if (event_code == LV_EVENT_VALUE_CHANGED) { + lv_obj_t* slider = lv_event_get_target_obj(event); + uint8_t brightness = (uint8_t)lv_slider_get_value(slider); + LOG_DBG("Brightness: %d%%", brightness); + change_brightness(brightness); + } +} + +void ble_checkbox_event(lv_event_t* event) +{ + int ret; + lv_event_code_t code = lv_event_get_code(event); + + if (code == LV_EVENT_VALUE_CHANGED) { + lv_obj_t* checkbox = lv_event_get_target(event); + bool checked = lv_obj_has_state(checkbox, LV_STATE_CHECKED); + + if (checked) { + // Enable Bluetooth + ret = enable_bluetooth_subsystem(); + if (ret != 0) { + LOG_ERR("Failed to enable bluethooth (err %d)", ret); + lv_obj_remove_state(checkbox, LV_STATE_CHECKED); + } else { + LOG_INF("Bluetooth enabled."); + } + } else { + // Disable Bluetooth + ret = disable_bluetooth_subsystem(); + if (ret != 0) { + LOG_ERR("Failed to disable bluethooth (err %d)", ret); + lv_obj_add_state(checkbox, LV_STATE_CHECKED); + } else { + LOG_INF("Bluetooth disabled."); + } + } + } +} + +/* MENU_SCREEN_INIT + * Create the menu screen using LVGL definitions. + */ +void settings_screen_init() +{ + // Create the screen object which is the LV object with no parent. + settings_screen = create_screen(); + + // Create a vertical flex layout container centered in the screen. + lv_obj_t* main_column = create_column(settings_screen, 100, 100); + + // Create a title row + lv_obj_t* title_row = create_row(main_column, 100, 15); + lv_obj_t* title_label = lv_label_create(title_row); + lv_label_set_text(title_label, "Settings"); + lv_obj_set_style_text_color(title_label, lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_text_font(title_label, &lv_font_montserrat_18, LV_PART_MAIN); + lv_obj_center(title_label); + + lv_obj_t* brightness_obj = lv_obj_create(main_column); + lv_obj_set_size(brightness_obj, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_flex_flow(brightness_obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(brightness_obj, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); + + lv_obj_t* lb_brightness = lv_label_create(brightness_obj); + lv_label_set_text(lb_brightness, "Brightness:"); + slider_brightness = lv_slider_create(brightness_obj); + lv_obj_set_width(slider_brightness, lv_pct(100)); + lv_slider_set_value(slider_brightness, 100, LV_ANIM_OFF); + + lv_obj_t* ble_obj = lv_obj_create(main_column); + lv_obj_set_size(ble_obj, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_flex_flow(ble_obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ble_obj, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); + + enable_ble = lv_checkbox_create(ble_obj); + lv_checkbox_set_text(enable_ble, "Enable BLE"); + lv_obj_set_width(enable_ble, lv_pct(100)); + lv_obj_add_state(enable_ble, LV_STATE_CHECKED); + lv_obj_set_style_text_font(enable_ble, &lv_font_montserrat_16, LV_PART_MAIN); + + // Add gesture detection only to the title area for going back to home screen + lv_obj_add_event_cb(title_row, settings_screen_event, LV_EVENT_ALL, NULL); + lv_obj_add_event_cb(slider_brightness, brightness_slider_event, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(enable_ble, ble_checkbox_event, LV_EVENT_VALUE_CHANGED, NULL); + LOG_DBG("Settings screen initialized successfully."); +} diff --git a/src/userinterface/screens/settings/settings.h b/src/userinterface/screens/settings/settings.h new file mode 100644 index 0000000..838290b --- /dev/null +++ b/src/userinterface/screens/settings/settings.h @@ -0,0 +1,30 @@ +/** Settings Screen Interface. + * Provides functionality to construct a settings screen using LVGL. + * + * @license GNU v3 + * @maintainer YehudaEi @ github + */ + +#ifndef _UI_SCREENS_SETTINGS_H +#define _UI_SCREENS_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lvgl.h" + +/* The screen object to be used in the userinterface. */ +extern lv_obj_t* settings_screen; + +/* The init implementation for the settings screen. */ +void settings_screen_init(); + +/* Event handler for settings screen gestures. It is used to detect non-list events. */ +void settings_screen_event(lv_event_t* event); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif