Compare commits

...

10 Commits

18 changed files with 705 additions and 181 deletions

View File

@ -748,7 +748,6 @@ void watch_peripherals_watch_sleep(void)
extern LCDConfig_t LCDConfig;
// First, we disable the display backlight and we set all the peripherals in their low power mode
lcd_set_backlight(&LCDConfig, 0);
//lcd_on(&LCDConfig, false);
lcd_sleep(&LCDConfig, true);
watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_Standby);
if(CST816D_sleep())

View File

@ -1,10 +1,106 @@
/**
* @file watch_power_management.h
* @author Anatole SCHRAMM-HENRY
* @brief Watch power management functions API header file
* @brief Watch power management functions API source file
* @version 0.1
* @date 2023-10-12
*
* @copyright MIT
*
*/
*/
#include "watch_power_management.h"
#include "app_common.h"
#include "lv_port_tick.h"
static struct
{
watch_power_state_e current_power_state;
enum CPU_CLK cpu_clock_idle;
enum CPU_CLK cpu_clock_full_speed;
} _watch_power_management = {
.current_power_state = WATCH_POWER_STATE_FULL_SPEED,
.cpu_clock_idle = CPU_CLK_80M,
.cpu_clock_full_speed = CPU_CLK_160M,
};
/**
* @brief Helper function to change the CPU clock of the micro.
* Internally checks that the new clock is different to the current one.
*
* @param cpu_clock the new frequency to apply @ref enum CPU_CLK
*/
static void _set_cpu_clock(enum CPU_CLK cpu_clock);
static enum CPU_CLK _cpu_frequency_to_CPU_CLK(uint32_t frequency);
static uint32_t _CPU_CLK_to_cpu_frequency(enum CPU_CLK cpu_clock);
void watch_power_management_change_power_state(watch_power_state_e power_state)
{
// If we are already in this power state, then there is nothing more to do.
if(power_state == _watch_power_management.current_power_state) return;
switch (power_state)
{
case WATCH_POWER_STATE_IDLE:
// We set the CPU clock to the value defined for the IDLE state
_set_cpu_clock(_watch_power_management.cpu_clock_idle);
break;
case WATCH_POWER_STATE_FULL_SPEED:
// We set the CPU clock to the value defined for the FULL SPEED state
_set_cpu_clock(_watch_power_management.cpu_clock_full_speed);
break;
case WATCH_POWER_STATE_SLEEP:
break;
case WATCH_POWER_STATE_BLE_SLEEP:
APP_LOG_INFO("Entering BLE sleep mode");
// We set the CPU clock to 40MHz (can't go lower or the BLE radio will stop working)
_set_cpu_clock(CPU_CLK_40M);
// We can stop the lvgl timer
APP_LOG_INFO("Stopping LVGL tick timer");
lv_port_tick_stop();
break;
case WACTH_POWER_STATE_STANDBY:
default:
break;
}
// Let's apply the new power state
_watch_power_management.current_power_state = power_state;
}
watch_power_state_e watch_power_management_get_current_power_state(void)
{
return _watch_power_management.current_power_state;
}
bool watch_power_management_check_current_power_state_is(watch_power_state_e power_state)
{
return power_state == _watch_power_management.current_power_state;
}
static void _set_cpu_clock(enum CPU_CLK cpu_clock)
{
// First let's get the current clock speed
tls_sys_clk clk;
tls_sys_clk_get(&clk);
// If the current clock is different from the clock we want to apply :
if(_cpu_frequency_to_CPU_CLK(clk.cpuclk) != cpu_clock)
{
tls_sys_clk_set(cpu_clock);
APP_LOG_INFO("New CPU frequency : %u MHz", _CPU_CLK_to_cpu_frequency(cpu_clock));
}
}
static enum CPU_CLK _cpu_frequency_to_CPU_CLK(uint32_t frequency)
{
return W800_PLL_CLK_MHZ / frequency;
}
static uint32_t _CPU_CLK_to_cpu_frequency(enum CPU_CLK cpu_clock)
{
return W800_PLL_CLK_MHZ / cpu_clock;
}

View File

@ -12,6 +12,9 @@
#ifndef WATCH_POWER_MANAGEMENT_H
#define WATCH_POWER_MANAGEMENT_H
#include "wm_type_def.h"
#include "wm_cpu.h"
typedef enum watch_power_state
{
/**
@ -47,9 +50,10 @@ typedef enum watch_power_state
WACTH_POWER_STATE_STANDBY,
} watch_power_state_e;
typedef struct watch_power_management
{
watch_power_state_e current_power_state;
} watch_power_management_t;
void watch_power_management_change_power_state(watch_power_state_e power_state);
watch_power_state_e watch_power_management_get_current_power_state(void);
bool watch_power_management_check_current_power_state_is(watch_power_state_e power_state);
#endif //WATCH_POWER_MANAGEMENT_H

View File

@ -1,6 +1,7 @@
#ifndef APP_LOG_H
#define APP_LOG_G
#include <stdio.h>
#include "app_common.h"
#include "app_config.h"

View File

@ -2,6 +2,8 @@
#include "watch_peripherals.h"
#include "watch_settings.h"
#include "app_log.h"
/***
* It is needed to have a reference on two header_titles because when
* switching from one screen using a header to an other screen which is also using one
@ -61,7 +63,7 @@ void common_screen_header_update_title(const char * title)
void common_screen_onclick_vibration(void)
{
uint16_t vibration_strength = persistency_get_settings()->display.display_vibrate_on_touch_strength*32;
uint16_t vibration_strength = (persistency_get_settings()->display.display_vibrate_on_touch_strength + 1)*32;
uint32_t vibration_duration_ms = 0;
if(persistency_get_settings()->display.display_vibrate_on_touch_duration)
vibration_duration_ms = persistency_get_settings()->display.display_vibrate_on_touch_duration*50 + 50;

View File

@ -16,6 +16,7 @@
#include "notification_screen.h"
#include "watch_peripherals.h"
#include "watch_settings.h"
#include "watch_power_management.h"
#include "firmware_version.h"
#include "MAX3010X.h"
@ -29,7 +30,6 @@ static void date_time_cb(struct tm * const dateTime)
tls_get_rtc(dateTime);
}
bool _is_in_ble_sleep_mode = false;
bool _is_ble_device_subscribed = false;
static void _perform_deferred_display_wake_up_set_timestamp(void);
static void _perform_deferred_display_wake_up(uint8_t deferred_time_in_ms);
@ -152,7 +152,7 @@ static void setTimeFormatCb(bool *hour_24H_format, SettingMode_e mode)
}
}
static void setDisplayVibrationDuration(uint8_t *duration, SettingMode_e mode)
static void setDisplayVibrationDurationCb(uint8_t *duration, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
@ -164,7 +164,7 @@ static void setDisplayVibrationDuration(uint8_t *duration, SettingMode_e mode)
}
}
static void setDisplayVibrationStrength(uint8_t *strength, SettingMode_e mode)
static void setDisplayVibrationStrengthCb(uint8_t *strength, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
@ -176,6 +176,78 @@ static void setDisplayVibrationStrength(uint8_t *strength, SettingMode_e mode)
}
}
static void setNotificationEnabledCb(bool *enabled, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*enabled = persistency_get_settings()->notification.notification_enabled;
}
else
{
watch_settings_notification_set_notification_enabled(*enabled);
}
}
static void setNotificationVibrationDurationCb(uint8_t *duration, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*duration = persistency_get_settings()->notification.notification_vibration_duration;
}
else
{
watch_settings_notification_set_notification_vibration_duration(*duration);
}
}
static void setNotificationVibrationStrengthCb(uint8_t *strength, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*strength = persistency_get_settings()->notification.notification_vibration_strength;
}
else
{
watch_settings_notification_set_notification_vibration_strength(*strength);
}
}
static void setCallEnabledCb(bool *enabled, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*enabled = persistency_get_settings()->notification.call_enabled;
}
else
{
watch_settings_notification_set_call_enabled(*enabled);
}
}
static void setCallVibrationDurationCb(uint8_t *duration, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*duration = persistency_get_settings()->notification.call_vibration_duration;
}
else
{
watch_settings_notification_set_call_vibration_duration(*duration);
}
}
static void setCallVibrationStrengthCb(uint8_t *strength, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*strength = persistency_get_settings()->notification.call_vibration_strength;
}
else
{
watch_settings_notification_set_call_vibration_strength(*strength);
}
}
static void setTimeoutCb(uint8_t *timeout, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
@ -342,8 +414,14 @@ SettingsScreenAPIInterface_t settingsScreenAPIInterface =
.setTimeFormatSettingsCb = &(setTimeFormatCb),
.setBrightnessSettingsCb = &(setGetBrightnessCb),
.setTimeoutSettingsCb = &(setTimeoutCb),
.setDisplayVibrationDurationSettingsCb = &(setDisplayVibrationDuration),
.setDisplayVibrationStrengthSettingsCb = &(setDisplayVibrationStrength),
.setDisplayVibrationDurationSettingsCb = &(setDisplayVibrationDurationCb),
.setDisplayVibrationStrengthSettingsCb = &(setDisplayVibrationStrengthCb),
.setNotificationEnabledSettingsCb = &(setNotificationEnabledCb),
.setNotificationVibrationDurationSettingsCb = &(setNotificationVibrationDurationCb),
.setNotificationVibrationStrengthSettingsCb = &(setNotificationVibrationStrengthCb),
.setCallEnabledSettingsCb = &(setCallEnabledCb),
.setCallVibrationDurationSettingsCb = &(setCallVibrationDurationCb),
.setCallVibrationStrengthSettingsCb = &(setCallVibrationStrengthCb),
.setOrientationSettingsCb = &(setOrientationCb),
.setWristTiltSettingsCb = &(setWristTiltCb),
.setBLEEnabledSettingsCb = &(setBLEEnabledCb),
@ -400,19 +478,22 @@ static void parser_event_cb(gadget_bridge_event_data_t *gadget_bridge_event_data
break;
case GADGET_BRIDGE_EVENT_TYPE_NOTIFY:
{
// Let's retrieve the time from the watch :
struct tm date_time;
tls_get_rtc(&date_time);
if(persistency_get_settings()->notification.notification_enabled)
{
// Let's retrieve the time from the watch :
struct tm date_time;
tls_get_rtc(&date_time);
notification_screen_notify(&notificationScreen, gadget_bridge_event_data->notification.handle,
mktime(&date_time),
gadget_bridge_event_data->notification.notification_type,
gadget_bridge_event_data->notification.title,
gadget_bridge_event_data->notification.body);
notification_screen_notify(&notificationScreen, gadget_bridge_event_data->notification.handle,
mktime(&date_time),
gadget_bridge_event_data->notification.notification_type,
gadget_bridge_event_data->notification.title,
gadget_bridge_event_data->notification.body);
//As we don't want the title and the body strings to be freed after the callback returns, let's set them to NULL
gadget_bridge_event_data->notification.title = NULL;
gadget_bridge_event_data->notification.body = NULL;
//As we don't want the title and the body strings to be freed after the callback returns, let's set them to NULL
gadget_bridge_event_data->notification.title = NULL;
gadget_bridge_event_data->notification.body = NULL;
}
}
break;
default:
@ -554,6 +635,30 @@ static void sendMusicPlaybackBLECommandCb(MusicPlaybackCtrlAction_e musicPlaybac
gadget_bridge_send_music_control(musicPlaybackCtrlAction);
}
static void notification_on_state_change_cb(NotificationState_e notificationState)
{
switch (notificationState)
{
case NOTIFICATION_STATE_DISPLAYED:
// Let's give a user feedback by vibrating the watch if it is configured to do so
if(persistency_get_settings()->notification.notification_vibration_duration)
{
uint16_t vibration_strength = (persistency_get_settings()->notification.notification_vibration_strength + 1)*32;
uint32_t vibration_duration_ms = 0;
if(persistency_get_settings()->notification.notification_vibration_duration)
vibration_duration_ms = persistency_get_settings()->notification.notification_vibration_duration*50 + 50;
uint16_t vibration_pattern[VIBRATION_PATTERN_SLOTS] = {vibration_duration_ms, vibration_duration_ms, vibration_duration_ms};
watch_peripherals_vibrate_with_pattern(vibration_strength > 255 ? 255 : vibration_strength, vibration_pattern);
}
break;
case NOTIFICATION_STATE_CLEARED:
default:
break;
}
}
extern LCDConfig_t LCDConfig;
void gfx_task(void *param)
@ -598,7 +703,7 @@ void gfx_task(void *param)
struct tm curr_time = {
.tm_mday = 1,
.tm_mon = 1,
.tm_year = 22, // Starting from 2000
.tm_year = 122, // Starting from 1900
};
tls_set_rtc(&curr_time);
}
@ -627,6 +732,7 @@ void gfx_task(void *param)
music_player_screen_register_music_player_time_ref_ms_cb(&musicPlayerScreen, &(elapsed_ms));
notification_screen_init(&notificationScreen);
notification_screen_register_on_state_change_cb(&notificationScreen, &(notification_on_state_change_cb));
settings_screen_init(&settingsScreen);
settings_screen_register_on_state_change_cb(&settingsScreen, &(settings_screen_on_state_change_cb));
@ -660,30 +766,16 @@ void gfx_task(void *param)
for(;;)
{
/* Actions to perform when the watch is active only */
if(!_is_in_ble_sleep_mode)
/* Actions to perform when the watch is active only, not in BLE sleep */
if(!watch_power_management_check_current_power_state_is(WATCH_POWER_STATE_BLE_SLEEP))
{
lv_timer_handler();
/* Throttle CPU freq down when inactive to save power or to increase responsiveness */
tls_sys_clk clk;
tls_sys_clk_get(&clk);
if(lv_disp_get_inactive_time(NULL) > 5000)
{
if(clk.cpuclk != 40)
{
tls_sys_clk_set(CPU_CLK_40M);
APP_LOG_DEBUG("CPU 40MHz");
}
}
watch_power_management_change_power_state(WATCH_POWER_STATE_IDLE);
else
{
if(clk.cpuclk != 160)
{
tls_sys_clk_set(CPU_CLK_160M);
APP_LOG_DEBUG("CPU 160MHz");
}
}
watch_power_management_change_power_state(WATCH_POWER_STATE_FULL_SPEED);
/* Will wake the display up after some ms to avoid seeing the second hand jumping */
_perform_deferred_display_wake_up(30);
@ -706,11 +798,7 @@ void gfx_task(void *param)
/* We need to keep the BLE stack running so we can't juste put the MCU in sleep mode :-( */
if(is_ble_modem_on())
{
APP_LOG_DEBUG("Entering BLE sleep mode");
/* We can stop the lvgl timer */
APP_LOG_TRACE("Stopping LVGL tick timer");
lv_port_tick_stop();
_is_in_ble_sleep_mode = true;
watch_power_management_change_power_state(WATCH_POWER_STATE_BLE_SLEEP);
}
else
{
@ -724,9 +812,10 @@ void gfx_task(void *param)
/* Let's sleep for real */
tls_pmu_sleep_start();
us_delay(100);
if(watch_peripherals_wakeup_source_is_user())
{
APP_LOG_INFO("User IO wakeup !");
/* Just to clear it off */
tls_pmu_timer0_stop();
watch_peripherals_wakeup_source_is_timer();
@ -734,7 +823,7 @@ void gfx_task(void *param)
}
/* Perform the periodic background tasks */
ms_delay(1);APP_LOG_INFO("Periodic timer wakeup !");
APP_LOG_INFO("Periodic timer wakeup !");
} while (watch_peripherals_wakeup_source_is_timer());
@ -796,17 +885,30 @@ void gfx_task(void *param)
}
}
bool wrist_tilt = false ,touch_screen_touch = false;
if((wrist_tilt = watch_peripherals_accelerometer_wrist_wakeup_interrupt()) || ((touch_screen_touch = lv_port_indev_touched()) && _is_in_ble_sleep_mode))
bool wrist_tilt = false ,touch_screen_touch = false, notification_received = false;
if(
(wrist_tilt = watch_peripherals_accelerometer_wrist_wakeup_interrupt()) ||
(notification_received = notification_screen_new_notification_available(&notificationScreen)) ||
((touch_screen_touch = lv_port_indev_touched()) && watch_power_management_check_current_power_state_is(WATCH_POWER_STATE_BLE_SLEEP))
)
{
if(wrist_tilt)
APP_LOG_DEBUG("Wrist tilt");
if(touch_screen_touch)
APP_LOG_DEBUG("Touch screen touch");
if(_is_in_ble_sleep_mode)
if(wrist_tilt)
{
_is_in_ble_sleep_mode = false;
lv_disp_trig_activity(NULL);
APP_LOG_DEBUG("Wrist tilt");
}
if(notification_received)
{
lv_disp_trig_activity(NULL);
APP_LOG_DEBUG("Notification received");
}
if(watch_power_management_check_current_power_state_is(WATCH_POWER_STATE_BLE_SLEEP))
{
watch_power_management_change_power_state(WATCH_POWER_STATE_IDLE);
lv_port_tick_start();
watch_face_force_sync(&watchFace);

View File

@ -313,7 +313,7 @@ void music_player_screen_create(MusicPlayerScreen_t * const musicPlayerScreen)
lv_obj_set_style_text_font(musicPlayerScreen->playPauseBtn.label, &lv_font_montserrat_30, LV_PART_MAIN);
lv_obj_center(musicPlayerScreen->playPauseBtn.label);
lv_obj_set_user_data(musicPlayerScreen->playPauseBtn.button, MUSIC_CONTROL_PLAY);
lv_obj_set_user_data(musicPlayerScreen->playPauseBtn.button, (void *)MUSIC_CONTROL_PLAY);
lv_obj_add_event_cb(musicPlayerScreen->playPauseBtn.button, &(music_player_button_click_event_cb), LV_EVENT_CLICKED, musicPlayerScreen);
//Previous track button

View File

@ -7,11 +7,13 @@
bool _notification_list_is_empty(NotificationDataList_t notificationList);
void _notification_list_add_head(NotificationDataList_t *notificationList, NotificationData_t *notification);
NotificationData_t *_notification_list_remove_tail(NotificationDataList_t *notificationList);
NotificationData_t *_notification_list_remove_by_handle(NotificationDataList_t *notificationList, uint32_t handle);
uint8_t _notification_list_count(NotificationDataList_t notificationList);
uint8_t _notification_list_unread_count(NotificationDataList_t notificationList);
void _notification_list_debug(NotificationDataList_t notificationList);
/* Internal UI API */
void _display_message_notification(NotificationScreen_t * const notificationScreen, const NotificationData_t *notification);
void _display_message_notification(NotificationScreen_t * const notificationScreen, NotificationData_t *notification);
void _notification_popup_destroy(NotificationScreen_t * const notificationScreen);
const char *_notification_type_to_char(NotificationType_e notificationType);
const char *_notification_timestamp_to_date(time_t timestamp);
@ -19,6 +21,7 @@ const char *_notification_timestamp_to_date(time_t timestamp);
static void notification_scrolled_event_cb(lv_event_t *e)
{
NotificationScreen_t *notificationScreen = lv_event_get_user_data(e);
NotificationData_t *notification = lv_obj_get_user_data(lv_event_get_target(e));
//If we didn't scroll down enough, make the notif pop again
if(lv_obj_get_scroll_y(e->target) >= 83)
{
@ -33,6 +36,8 @@ static void notification_scrolled_event_cb(lv_event_t *e)
{
LV_LOG_USER("Notification closed");
_notification_popup_destroy(notificationScreen);
notificationScreen->new_notification_available = false;
notification->read = true;
if(notificationScreen->notificationOnStateChangeCb) notificationScreen->notificationOnStateChangeCb(NOTIFICATION_STATE_CLEARED);
}
}
@ -97,17 +102,44 @@ void notification_screen_notify(NotificationScreen_t * const notificationScreen,
notification->read = false;
_notification_list_add_head(&notificationScreen->notificationList, notification);
notificationScreen->new_notification_available = true;
switch(notificationType)
{
case NOTIFICATION_TYPE_CALL:
break;
default:
_display_message_notification(notificationScreen, notification);
if(notificationScreen->notificationOnStateChangeCb) notificationScreen->notificationOnStateChangeCb(NOTIFICATION_STATE_DISPLAYED);
_display_message_notification(notificationScreen, notification);
}
}
bool notification_screen_new_notification_available(NotificationScreen_t * const notificationScreen)
{
if(!notificationScreen)
{
LV_LOG_ERROR("NULL pointer given !");
return false;
}
if(notificationScreen->new_notification_available)
{
notificationScreen->new_notification_available = false;
return true;
}
return false;
}
uint8_t notification_screen_notification_count(NotificationScreen_t * const notificationScreen)
{
return _notification_list_count(notificationScreen->notificationList);
}
uint8_t notification_screen_unread_notification_count(NotificationScreen_t * const notificationScreen)
{
return _notification_list_unread_count(notificationScreen->notificationList);;
}
void notification_screen_destroy(NotificationScreen_t * const notificationScreen)
{
if(!notificationScreen)
@ -162,6 +194,39 @@ NotificationData_t *_notification_list_remove_tail(NotificationDataList_t *notif
return toReturn;
}
NotificationData_t *_notification_list_remove_by_handle(NotificationDataList_t *notificationList, uint32_t handle)
{
if(!notificationList) return NULL;
if(_notification_list_is_empty(*notificationList)) return NULL;
NotificationData_t *toReturn = NULL;
//There is only one item in the list
if((*notificationList)->next == NULL)
{
if((*notificationList)->handle == handle)
{
toReturn = *notificationList;
*notificationList = NULL;
}
return toReturn;
}
NotificationDataList_t cursor = *notificationList;
while(!_notification_list_is_empty(cursor->next))
{
if(cursor->next->handle == handle)
{
toReturn = cursor->next;
cursor->next = NULL;
return toReturn;
}
cursor = cursor->next;
}
return toReturn;
}
uint8_t _notification_list_count(NotificationDataList_t notificationList)
{
uint8_t count = 0;
@ -174,7 +239,19 @@ uint8_t _notification_list_count(NotificationDataList_t notificationList)
return count;
}
void _display_message_notification(NotificationScreen_t * const notificationScreen, const NotificationData_t *notification)
uint8_t _notification_list_unread_count(NotificationDataList_t notificationList)
{
uint8_t count = 0;
while(!_notification_list_is_empty(notificationList))
{
if(!notificationList->read)count++;
notificationList = notificationList->next;
}
return count;
}
void _display_message_notification(NotificationScreen_t * const notificationScreen, NotificationData_t *notification)
{
//Create and display a graphical widget containing the notification
lv_obj_t *notification_display = lv_layer_top();
@ -190,6 +267,8 @@ void _display_message_notification(NotificationScreen_t * const notificationScre
2) A notification is currently being shown and all UI elements were already created / allocated
*/
lv_obj_set_user_data(notification_display, notification);
if(lv_obj_get_child_cnt(notification_display) == 0)
{
//Only allow to scroll down and not up (LV_DIR_TOP makes it, is it a bug ?)
@ -288,6 +367,7 @@ void _display_message_notification(NotificationScreen_t * const notificationScre
void _notification_popup_destroy(NotificationScreen_t * const notificationScreen)
{
lv_obj_clean(lv_layer_top());
lv_obj_remove_event_cb_with_user_data(lv_layer_top(), &(notification_scrolled_event_cb), notificationScreen);
notificationScreen->type_label = NULL;
notificationScreen->title_label = NULL;
notificationScreen->date_label = NULL;

View File

@ -16,7 +16,7 @@ typedef enum NotificationType
NOTIFICATION_TYPE_WHATSAPP,
NOTIFICATION_TYPE_GADGET_BRIDGE,
NOTIFICATION_TYPE_UNKNOWN,
/* This enum value has no match in GadgetBridge's enum */
// This enum value has no match in GadgetBridge's enum
NOTIFICATION_TYPE_CALL,
} NotificationType_e;
@ -42,20 +42,22 @@ typedef void (*NotificationOnStateChangeCb_t)(NotificationState_e notificationSt
typedef struct NotificationScreen
{
//Can be erased attributes
// Can be erased attributes
lv_obj_t *display;
//Should not be erased attributes
//Notification UI object
// Should not be erased attributes
// Notification UI object
lv_obj_t *type_label;
lv_obj_t *title_label;
lv_obj_t *date_label;
lv_obj_t *body_label;
NotificationOnStateChangeCb_t notificationOnStateChangeCb;
//Notification history data structure
// Notification history data structure
NotificationData_t notificationPool[MAX_NOTIFICATIONS_COUNT];
NotificationDataList_t notificationList; //Actual notifications
NotificationDataList_t freeNotificationList; //Free notification object pool
NotificationDataList_t notificationList; // Actual notifications
NotificationDataList_t freeNotificationList; // Free notification object pool
// Miscellaneous
bool new_notification_available;
} NotificationScreen_t;
void notification_screen_init(NotificationScreen_t * const notificationScreen);
@ -64,6 +66,12 @@ void notification_screen_register_on_state_change_cb(NotificationScreen_t * cons
void notification_screen_notify(NotificationScreen_t * const notificationScreen, uint32_t handle, time_t dateOfArrival, NotificationType_e notificationType, char * title, char * body);
bool notification_screen_new_notification_available(NotificationScreen_t * const notificationScreen);
uint8_t notification_screen_notification_count(NotificationScreen_t * const notificationScreen);
uint8_t notification_screen_unread_notification_count(NotificationScreen_t * const notificationScreen);
void notification_screen_create(NotificationScreen_t * const notificationScreen);
void notification_screen_destroy(NotificationScreen_t * const notificationScreen);

View File

@ -16,10 +16,30 @@ static const char *date_format = "dd/mm/yyyy\ndd/mm/yy\nyyyy/mm/dd\nyy/mm/dd";
static const char *timeout_options = "Off\n5 seconds\n10 seconds\n15 seconds\n20 seconds\n25 seconds\n30 seconds\n35 seconds\n40 seconds\n45 seconds\n50 seconds\n55 seconds\n60 seconds";
static const char *orientation_format = "Default\n90°\n180°\n270°";
static const char* vibration_duration = "None\n100 ms\n150 ms\n200 ms\n250 ms\n300 ms\n350 ms\n400 ms";
static const char* vibration_force = "1\n2\n3\n4\n5\n6\n7\n8";
static const char* vibration_strength = "1\n2\n3\n4\n5\n6\n7\n8";
static const char* language_options = "Francais\nDeutsch\nEnglish";
typedef enum roller_id
{
ROLLER_ID_TOUCH_VIBRATION_DURATION = 0,
ROLLER_ID_TOUCH_VIBRATION_STRENGTH,
ROLLER_ID_NOTIFICATION_VIBRATION_DURATION,
ROLLER_ID_NOTIFICATION_VIBRATION_STRENGTH,
ROLLER_ID_CALL_VIBRATION_DURATION,
ROLLER_ID_CALL_VIBRATION_STRENGTH,
} roller_id_e;
typedef enum switch_id
{
SWITCH_ID_BLE_ENABLE = 0,
SWITCH_ID_WIFI_ENABLE,
SWITCH_ID_WRIST_TILT_ENABLE,
SWITCH_ID_AUTOMATIC_TIME_ENABLE,
SWITCH_ID_NOTIFICATION_ENABLE,
SWITCH_ID_CALL_ENABLED,
} switch_id_e;
static lv_obj_t *add_menu_list_item(lv_obj_t *list, const char *text, lv_event_cb_t event_cb, void *user_data, SettingsScreenCategory_e category);
static void update_menu_list_item_text(lv_obj_t *menu_list_item, const char *text);
@ -28,7 +48,6 @@ static void _set_rtc_time_to_label(SettingsScreen_t * const settingsScreen);
static void _set_battery_voltage_to_label(SettingsScreen_t * const settingsScreen);
static void _set_magnetometer_data_to_label(SettingsScreen_t * const settingsScreen);
static void _set_bmp280_data_to_label(SettingsScreen_t * const settingsScreen);
static void _reset_switch_pointers(SettingsScreen_t * const settingsScreen);
static void _enable_time_and_date_rollers(bool enabled, SettingsScreen_t * const settingsScreen);
static void _show_ble_pairing_key(SettingsScreen_t * const settingsScreen, bool show);
@ -161,30 +180,48 @@ static void brightness_slider_cb(lv_event_t *e)
settingsScreen->settingsScreenAPIInterface.setBrightnessSettingsCb(&brightness, SETTING_MODE_SET);
}
static void vibration_duration_roller_cb(lv_event_t *e)
static void vibration_typed_roller_cb(lv_event_t *e)
{
SettingsScreen_t *settingsScreen = e->user_data;
if(!settingsScreen->settingsScreenAPIInterface.setDisplayVibrationDurationSettingsCb) return;
lv_obj_t *roller = lv_event_get_target(e);
uint8_t index = lv_roller_get_selected(roller);
roller_id_e roller_id = (roller_id_e) lv_obj_get_user_data(roller);
settingsScreen->settingsScreenAPIInterface.setDisplayVibrationDurationSettingsCb(&index, SETTING_MODE_SET);
common_screen_onclick_vibration();
}
static void vibration_strength_roller_cb(lv_event_t *e)
{
SettingsScreen_t *settingsScreen = e->user_data;
if(!settingsScreen->settingsScreenAPIInterface.setDisplayVibrationStrengthSettingsCb) return;
lv_obj_t *roller = lv_event_get_target(e);
uint8_t index = lv_roller_get_selected(roller);
settingsScreen->settingsScreenAPIInterface.setDisplayVibrationStrengthSettingsCb(&index, SETTING_MODE_SET);
common_screen_onclick_vibration();
switch(roller_id)
{
case ROLLER_ID_TOUCH_VIBRATION_DURATION:
if (!settingsScreen->settingsScreenAPIInterface.setDisplayVibrationDurationSettingsCb)
return;
settingsScreen->settingsScreenAPIInterface.setDisplayVibrationDurationSettingsCb(&index, SETTING_MODE_SET);
common_screen_onclick_vibration();
break;
case ROLLER_ID_TOUCH_VIBRATION_STRENGTH:
if(!settingsScreen->settingsScreenAPIInterface.setDisplayVibrationStrengthSettingsCb)
return;
settingsScreen->settingsScreenAPIInterface.setDisplayVibrationStrengthSettingsCb(&index, SETTING_MODE_SET);
common_screen_onclick_vibration();
break;
case ROLLER_ID_NOTIFICATION_VIBRATION_DURATION:
if (!settingsScreen->settingsScreenAPIInterface.setNotificationVibrationDurationSettingsCb)
return;
settingsScreen->settingsScreenAPIInterface.setNotificationVibrationDurationSettingsCb(&index, SETTING_MODE_SET);
break;
case ROLLER_ID_NOTIFICATION_VIBRATION_STRENGTH:
if (!settingsScreen->settingsScreenAPIInterface.setNotificationVibrationStrengthSettingsCb)
return;
settingsScreen->settingsScreenAPIInterface.setNotificationVibrationStrengthSettingsCb(&index, SETTING_MODE_SET);
break;
case ROLLER_ID_CALL_VIBRATION_DURATION:
if (!settingsScreen->settingsScreenAPIInterface.setCallVibrationDurationSettingsCb)
return;
settingsScreen->settingsScreenAPIInterface.setCallVibrationDurationSettingsCb(&index, SETTING_MODE_SET);
break;
case ROLLER_ID_CALL_VIBRATION_STRENGTH:
if (!settingsScreen->settingsScreenAPIInterface.setCallVibrationStrengthSettingsCb)
return;
settingsScreen->settingsScreenAPIInterface.setCallVibrationStrengthSettingsCb(&index, SETTING_MODE_SET);
break;
}
}
static void timeout_roller_cb(lv_event_t * e)
@ -212,27 +249,38 @@ static void orientation_dropdown_cb(lv_event_t *e)
static void activation_switch_cb(lv_event_t *e)
{
SettingsScreen_t *settingsScreen = e->user_data;
SettingsScreen_t *settingsScreen = lv_event_get_user_data(e);
lv_obj_t *switch_obj = lv_event_get_target(e);
bool toggled = lv_obj_has_state(switch_obj, LV_STATE_CHECKED);
switch_id_e switch_id = (switch_id_e) lv_obj_get_user_data(switch_obj);
bool toggled = lv_obj_has_state(e->target, LV_STATE_CHECKED);
if(e->target == settingsScreen->ble_switch)
switch(switch_id)
{
if(settingsScreen->settingsScreenAPIInterface.setBLEEnabledSettingsCb)settingsScreen->settingsScreenAPIInterface.setBLEEnabledSettingsCb(&toggled, SETTING_MODE_SET);
_show_ble_pairing_key(settingsScreen, toggled);
}
else if(e->target == settingsScreen->wifi_switch)
{
if(settingsScreen->settingsScreenAPIInterface.setWiFiEnabledSettingsCb)settingsScreen->settingsScreenAPIInterface.setWiFiEnabledSettingsCb(&toggled, SETTING_MODE_SET);
}
else if(e->target == settingsScreen->wrist_tilt_switch)
{
if(settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb)settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb(&toggled, SETTING_MODE_SET);
}
else if(e->target == settingsScreen->auto_set_time_switch)
{
if(settingsScreen->settingsScreenAPIInterface.setAutomaticTimeSettingsCb)settingsScreen->settingsScreenAPIInterface.setAutomaticTimeSettingsCb(&toggled, SETTING_MODE_SET);
_enable_time_and_date_rollers(!toggled, settingsScreen);
case SWITCH_ID_BLE_ENABLE:
if(settingsScreen->settingsScreenAPIInterface.setBLEEnabledSettingsCb)
settingsScreen->settingsScreenAPIInterface.setBLEEnabledSettingsCb(&toggled, SETTING_MODE_SET);
_show_ble_pairing_key(settingsScreen, toggled);
break;
case SWITCH_ID_WIFI_ENABLE:
if(settingsScreen->settingsScreenAPIInterface.setWiFiEnabledSettingsCb)
settingsScreen->settingsScreenAPIInterface.setWiFiEnabledSettingsCb(&toggled, SETTING_MODE_SET);
break;
case SWITCH_ID_WRIST_TILT_ENABLE:
if(settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb)
settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb(&toggled, SETTING_MODE_SET);
break;
case SWITCH_ID_AUTOMATIC_TIME_ENABLE:
if(settingsScreen->settingsScreenAPIInterface.setAutomaticTimeSettingsCb)settingsScreen->settingsScreenAPIInterface.setAutomaticTimeSettingsCb(&toggled, SETTING_MODE_SET);
_enable_time_and_date_rollers(!toggled, settingsScreen);
break;
case SWITCH_ID_NOTIFICATION_ENABLE:
if(settingsScreen->settingsScreenAPIInterface.setNotificationEnabledSettingsCb)
settingsScreen->settingsScreenAPIInterface.setNotificationEnabledSettingsCb(&toggled, SETTING_MODE_SET);
break;
case SWITCH_ID_CALL_ENABLED:
if(settingsScreen->settingsScreenAPIInterface.setCallEnabledSettingsCb)
settingsScreen->settingsScreenAPIInterface.setCallEnabledSettingsCb(&toggled, SETTING_MODE_SET);
break;
}
}
@ -284,23 +332,24 @@ static void load_time_and_date_side_screen(SettingsScreen_t *settingsScreen)
lv_obj_t *label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Set Time & Date :");
settingsScreen->auto_set_time_switch = lv_switch_create(settingsScreen->side_screen);
lv_obj_align_to(settingsScreen->auto_set_time_switch, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_t *switch_obj = lv_switch_create(settingsScreen->side_screen);
lv_obj_set_user_data(switch_obj, (void *)SWITCH_ID_AUTOMATIC_TIME_ENABLE);
lv_obj_align_to(switch_obj, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
bool auto_set_enable = false;
if(settingsScreen->settingsScreenAPIInterface.setAutomaticTimeSettingsCb)settingsScreen->settingsScreenAPIInterface.setAutomaticTimeSettingsCb(&auto_set_enable, SETTING_MODE_GET);
if(auto_set_enable)
{
lv_obj_add_state(settingsScreen->auto_set_time_switch, LV_STATE_CHECKED);
lv_obj_add_state(switch_obj, LV_STATE_CHECKED);
}
lv_obj_add_event_cb(settingsScreen->auto_set_time_switch, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
lv_obj_add_event_cb(switch_obj, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Automatic");
lv_obj_align_to(label, settingsScreen->auto_set_time_switch, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, switch_obj, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Time :");
lv_obj_align_to(label, settingsScreen->auto_set_time_switch, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_align_to(label, switch_obj, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
settingsScreen->hour_roller = lv_roller_create(settingsScreen->side_screen);
settingsScreen->minute_roller = lv_roller_create(settingsScreen->side_screen);
@ -434,73 +483,150 @@ static void load_display_side_screen(SettingsScreen_t *settingsScreen)
lv_label_set_text_static(label, "Wakeup :");
lv_obj_align_to(label, orientation_dropdown, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
settingsScreen->wrist_tilt_switch = lv_switch_create(settingsScreen->side_screen);
lv_obj_t *switch_obj = lv_switch_create(settingsScreen->side_screen);
lv_obj_set_user_data(switch_obj, (void *)SWITCH_ID_WRIST_TILT_ENABLE);
bool toggled = false;
if(settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb)settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb(&toggled, SETTING_MODE_GET);
if(toggled)lv_obj_add_state(settingsScreen->wrist_tilt_switch, LV_STATE_CHECKED);
lv_obj_align_to(settingsScreen->wrist_tilt_switch, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_add_event_cb(settingsScreen->wrist_tilt_switch, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
if(toggled)lv_obj_add_state(switch_obj, LV_STATE_CHECKED);
lv_obj_align_to(switch_obj, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_add_event_cb(switch_obj, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Wrist Tilt");
lv_obj_align_to(label, settingsScreen->wrist_tilt_switch, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, switch_obj, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate On Touch :");
lv_obj_align_to(label, settingsScreen->wrist_tilt_switch, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_align_to(label, switch_obj, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_t *on_touch_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_obj_set_user_data(on_touch_vibration_duration_roller, (void *)ROLLER_ID_TOUCH_VIBRATION_DURATION);
lv_roller_set_visible_row_count(on_touch_vibration_duration_roller, 2);
uint8_t duration = 0;
if(settingsScreen->settingsScreenAPIInterface.setDisplayVibrationDurationSettingsCb)settingsScreen->settingsScreenAPIInterface.setDisplayVibrationDurationSettingsCb(&duration, SETTING_MODE_GET);
lv_roller_set_selected(on_touch_vibration_duration_roller, duration, LV_ANIM_OFF);
lv_obj_add_event_cb(on_touch_vibration_duration_roller, &(vibration_duration_roller_cb), LV_EVENT_RELEASED, settingsScreen);
lv_obj_add_event_cb(on_touch_vibration_duration_roller, &(vibration_typed_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Duration");
lv_obj_align_to(label, on_touch_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, on_touch_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
lv_obj_t *on_touch_vibration_strength_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_strength_roller, on_touch_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_strength_roller, vibration_force, LV_ROLLER_MODE_NORMAL);
lv_roller_set_options(on_touch_vibration_strength_roller, vibration_strength, LV_ROLLER_MODE_NORMAL);
lv_obj_set_user_data(on_touch_vibration_strength_roller, (void *)ROLLER_ID_TOUCH_VIBRATION_STRENGTH);
lv_roller_set_visible_row_count(on_touch_vibration_strength_roller, 2);
uint8_t strength = 0;
if(settingsScreen->settingsScreenAPIInterface.setDisplayVibrationStrengthSettingsCb)settingsScreen->settingsScreenAPIInterface.setDisplayVibrationStrengthSettingsCb(&strength, SETTING_MODE_GET);
lv_roller_set_selected(on_touch_vibration_strength_roller, strength, LV_ANIM_OFF);
lv_obj_set_width(on_touch_vibration_strength_roller, lv_obj_get_width(on_touch_vibration_duration_roller));
lv_obj_add_event_cb(on_touch_vibration_strength_roller, &(vibration_strength_roller_cb), LV_EVENT_RELEASED, settingsScreen);
lv_obj_add_event_cb(on_touch_vibration_strength_roller, &(vibration_typed_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Strength");
lv_obj_align_to(label, on_touch_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, on_touch_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
static void load_notifications_side_screen(SettingsScreen_t *settingsScreen)
{
lv_obj_t *label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate on\nnotifications :");
// Notification enable switch
lv_obj_t *notification_enable_switch = lv_switch_create(settingsScreen->side_screen);
lv_obj_set_user_data(notification_enable_switch, (void *)SWITCH_ID_NOTIFICATION_ENABLE);
bool toggled = false;
if(settingsScreen->settingsScreenAPIInterface.setNotificationEnabledSettingsCb)
settingsScreen->settingsScreenAPIInterface.setNotificationEnabledSettingsCb(&toggled, SETTING_MODE_GET);
if(toggled)lv_obj_add_state(notification_enable_switch, LV_STATE_CHECKED);
lv_obj_add_event_cb(notification_enable_switch, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
lv_obj_t *on_touch_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_touch_vibration_duration_roller, 2);
//lv_obj_add_event_cb(vibration_duration_roller, &(vibration_duration_roller_cb), LV_EVENT_RELEASED, settingsScreen);
lv_obj_t * label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Notifications");
lv_obj_align_to(label, notification_enable_switch, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate on\nnotifications :");
lv_obj_align_to(label, notification_enable_switch, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_t *on_notification_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_notification_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_notification_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_obj_set_user_data(on_notification_vibration_duration_roller, (void *)ROLLER_ID_NOTIFICATION_VIBRATION_DURATION);
lv_roller_set_visible_row_count(on_notification_vibration_duration_roller, 2);
uint8_t duration = 0;
if(settingsScreen->settingsScreenAPIInterface.setNotificationVibrationDurationSettingsCb)
settingsScreen->settingsScreenAPIInterface.setNotificationVibrationDurationSettingsCb(&duration, SETTING_MODE_GET);
lv_roller_set_selected(on_notification_vibration_duration_roller, duration, LV_ANIM_OFF);
lv_obj_add_event_cb(on_notification_vibration_duration_roller, &(vibration_typed_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Duration");
lv_obj_align_to(label, on_touch_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, on_notification_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
lv_obj_t *on_touch_vibration_force_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_force_roller, on_touch_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_force_roller, vibration_force, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_touch_vibration_force_roller, 2);
lv_obj_set_width(on_touch_vibration_force_roller, lv_obj_get_width(on_touch_vibration_duration_roller));
lv_obj_t *on_notification_vibration_strength_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_notification_vibration_strength_roller, on_notification_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_notification_vibration_strength_roller, vibration_strength, LV_ROLLER_MODE_NORMAL);
lv_obj_set_user_data(on_notification_vibration_strength_roller, (void *)ROLLER_ID_NOTIFICATION_VIBRATION_STRENGTH);
lv_roller_set_visible_row_count(on_notification_vibration_strength_roller, 2);
uint8_t strength = 0;
if(settingsScreen->settingsScreenAPIInterface.setNotificationVibrationStrengthSettingsCb)
settingsScreen->settingsScreenAPIInterface.setNotificationVibrationStrengthSettingsCb(&strength, SETTING_MODE_GET);
lv_roller_set_selected(on_notification_vibration_strength_roller, strength, LV_ANIM_OFF);
lv_obj_set_width(on_notification_vibration_strength_roller, lv_obj_get_width(on_notification_vibration_duration_roller));
lv_obj_add_event_cb(on_notification_vibration_strength_roller, &(vibration_typed_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Force");
lv_obj_align_to(label, on_touch_vibration_force_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_label_set_text_static(label, "Strength");
lv_obj_align_to(label, on_notification_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
// Call enable switch
lv_obj_t *call_enable_switch = lv_switch_create(settingsScreen->side_screen);
lv_obj_set_user_data(call_enable_switch, (void *)SWITCH_ID_CALL_ENABLED);
toggled = false;
if(settingsScreen->settingsScreenAPIInterface.setCallEnabledSettingsCb)
settingsScreen->settingsScreenAPIInterface.setCallEnabledSettingsCb(&toggled, SETTING_MODE_GET);
if(toggled)lv_obj_add_state(call_enable_switch, LV_STATE_CHECKED);
lv_obj_align_to(call_enable_switch, on_notification_vibration_strength_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_add_event_cb(call_enable_switch, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Calls");
lv_obj_align_to(label, call_enable_switch, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate on calls :");
lv_obj_align_to(label, call_enable_switch, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_t *on_call_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_call_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_call_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_obj_set_user_data(on_call_vibration_duration_roller, (void *)ROLLER_ID_CALL_VIBRATION_DURATION);
lv_roller_set_visible_row_count(on_call_vibration_duration_roller, 2);
duration = 0;
if(settingsScreen->settingsScreenAPIInterface.setCallVibrationDurationSettingsCb)
settingsScreen->settingsScreenAPIInterface.setCallVibrationDurationSettingsCb(&duration, SETTING_MODE_GET);
lv_roller_set_selected(on_call_vibration_duration_roller, duration, LV_ANIM_OFF);
lv_obj_add_event_cb(on_call_vibration_duration_roller, &(vibration_typed_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Duration");
lv_obj_align_to(label, on_call_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
lv_obj_t *on_call_vibration_strength_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_call_vibration_strength_roller, on_call_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_call_vibration_strength_roller, vibration_strength, LV_ROLLER_MODE_NORMAL);
lv_obj_set_user_data(on_call_vibration_strength_roller, (void *)ROLLER_ID_CALL_VIBRATION_STRENGTH);
lv_roller_set_visible_row_count(on_call_vibration_strength_roller, 2);
strength = 0;
if(settingsScreen->settingsScreenAPIInterface.setCallVibrationStrengthSettingsCb)
settingsScreen->settingsScreenAPIInterface.setCallVibrationStrengthSettingsCb(&strength, SETTING_MODE_GET);
lv_roller_set_selected(on_call_vibration_strength_roller, strength, LV_ANIM_OFF);
lv_obj_set_width(on_call_vibration_strength_roller, lv_obj_get_width(on_call_vibration_duration_roller));
lv_obj_add_event_cb(on_call_vibration_strength_roller, &(vibration_typed_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Strength");
lv_obj_align_to(label, on_call_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
static void load_connectivity_side_screen(SettingsScreen_t *settingsScreen)
@ -509,6 +635,7 @@ static void load_connectivity_side_screen(SettingsScreen_t *settingsScreen)
lv_label_set_text_static(label, "Connectivity :");
settingsScreen->ble_switch = lv_switch_create(settingsScreen->side_screen);
lv_obj_set_user_data(settingsScreen->ble_switch, (void *)SWITCH_ID_BLE_ENABLE);
lv_obj_align_to(settingsScreen->ble_switch, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
bool ble_toggled = false;
if(settingsScreen->settingsScreenAPIInterface.setBLEEnabledSettingsCb)settingsScreen->settingsScreenAPIInterface.setBLEEnabledSettingsCb(&ble_toggled, SETTING_MODE_GET);
@ -561,6 +688,7 @@ static void load_connectivity_side_screen(SettingsScreen_t *settingsScreen)
lv_obj_align_to(settingsScreen->ble_mac_addr.label, settingsScreen->ble_dev_mac_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5);
settingsScreen->wifi_switch = lv_switch_create(settingsScreen->side_screen);
lv_obj_set_user_data(settingsScreen->wifi_switch, (void *)SWITCH_ID_WIFI_ENABLE);
lv_obj_align_to(settingsScreen->wifi_switch, settingsScreen->ble_mac_addr.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
bool wifi_toggled = false;
if(settingsScreen->settingsScreenAPIInterface.setWiFiEnabledSettingsCb)settingsScreen->settingsScreenAPIInterface.setWiFiEnabledSettingsCb(&wifi_toggled, SETTING_MODE_GET);
@ -842,7 +970,6 @@ static void _simulate_side_screen_item_click(SettingsScreen_t * const settingsSc
settingsScreen->last_selected_item = item;
lv_obj_clean(settingsScreen->side_screen);
_reset_switch_pointers(settingsScreen);
if(item == settingsScreen->time_and_date_item)
{
@ -924,14 +1051,6 @@ static void _set_bmp280_data_to_label(SettingsScreen_t * const settingsScreen)
lv_label_set_text_static(settingsScreen->bmp280_temperature.label, settingsScreen->bmp280_temperature.text);
}
static void _reset_switch_pointers(SettingsScreen_t * const settingsScreen)
{
settingsScreen->auto_set_time_switch = NULL;
settingsScreen->wrist_tilt_switch = NULL;
settingsScreen->ble_switch = NULL;
settingsScreen->wifi_switch = NULL;
}
static void _enable_time_and_date_rollers(bool enabled, SettingsScreen_t * const settingsScreen)
{
if(enabled)

View File

@ -18,8 +18,14 @@ typedef struct SettingsScreenAPIInterface
void (*setTimeoutSettingsCb)(uint8_t *timeout, SettingMode_e mode);
void (*setOrientationSettingsCb)(uint8_t *orientation, SettingMode_e mode);
void (*setWristTiltSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setNotificationEnabledSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setDisplayVibrationDurationSettingsCb)(uint8_t *duration, SettingMode_e mode);
void (*setDisplayVibrationStrengthSettingsCb)(uint8_t *strength, SettingMode_e mode);
void (*setCallEnabledSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setNotificationVibrationDurationSettingsCb)(uint8_t *duration, SettingMode_e mode);
void (*setNotificationVibrationStrengthSettingsCb)(uint8_t *strength, SettingMode_e mode);
void (*setCallVibrationDurationSettingsCb)(uint8_t *duration, SettingMode_e mode);
void (*setCallVibrationStrengthSettingsCb)(uint8_t *strength, SettingMode_e mode);
void (*setBLEEnabledSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setWiFiEnabledSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setLanguageSettingsCb)(uint8_t *language, SettingMode_e mode);
@ -67,7 +73,6 @@ typedef struct SettingsScreen
lv_obj_t *side_screen;
/* Menu widgets */
lv_obj_t *auto_set_time_switch;
lv_obj_t *hour_roller;
lv_obj_t *minute_roller;
lv_obj_t *second_roller;
@ -76,7 +81,6 @@ typedef struct SettingsScreen
lv_obj_t *day_roller;
lv_obj_t *month_roller;
lv_obj_t *year_roller;
lv_obj_t *wrist_tilt_switch;
lv_obj_t *wifi_switch;
lv_obj_t *wifi_label;
lv_obj_t *ble_switch;

View File

@ -29,10 +29,12 @@ static const WatchSettings_t defaultWatchSettings =
.activity_step_counter_en = true,
},
.notification = {
.notification_vibration_duration = 3,
.notification_enabled = true,
.notification_vibration_duration = 0,
.notification_vibration_strength = 6,
.notification_vibrate_on_notification_receive = true,
.notification_vibrate_on_call_receive = true,
.call_enabled = true,
.call_vibration_duration = 0,
.call_vibration_strength = 6,
},
.connectivity = {
.connectivity_ble_enabled = false,
@ -111,18 +113,42 @@ void watch_settings_display_set_vibrate_on_touch_duration(uint8_t duration)
_params_changed = true;
}
void watch_settings_notification_set_vibration_strength(uint8_t level)
void watch_settings_notification_set_notification_enabled(bool enabled)
{
watchSettings.notification.notification_enabled = enabled;
_params_changed = true;
}
void watch_settings_notification_set_notification_vibration_strength(uint8_t level)
{
watchSettings.notification.notification_vibration_strength = level;
_params_changed = true;
}
void watch_settings_notification_set_vibration_duration(uint8_t duration)
void watch_settings_notification_set_notification_vibration_duration(uint8_t duration)
{
watchSettings.notification.notification_vibration_duration = duration;
_params_changed = true;
}
void watch_settings_notification_set_call_enabled(bool enabled)
{
watchSettings.notification.call_enabled = enabled;
_params_changed = true;
}
void watch_settings_notification_set_call_vibration_strength(uint8_t level)
{
watchSettings.notification.call_vibration_strength = level;
_params_changed = true;
}
void watch_settings_notification_set_call_vibration_duration(uint8_t duration)
{
watchSettings.notification.call_vibration_duration = duration;
_params_changed = true;
}
void watch_settings_connectivity_set_ble_enabled(bool enabled)
{
watchSettings.connectivity.connectivity_ble_enabled = enabled;

View File

@ -51,10 +51,12 @@ typedef struct Activity
*/
typedef struct Notification
{
uint32_t notification_vibrate_on_notification_receive:1,
notification_vibrate_on_call_receive:1,
uint32_t notification_enabled:1, // Enable or disable messages notifications
notification_vibration_strength:3,
notification_vibration_duration:3;
notification_vibration_duration:3,
call_enabled:1, // Enable or disable calls notifications
call_vibration_strength:3,
call_vibration_duration:3;
} Notification_t;
/**
@ -174,19 +176,47 @@ void watch_settings_display_set_vibrate_on_touch_strength(uint8_t level);
*/
void watch_settings_display_set_vibrate_on_touch_duration(uint8_t duration);
/**
* @brief
*
* @param enabled
*/
void watch_settings_notification_set_notification_enabled(bool enabled);
/**
* @brief
*
* @param level
*/
void watch_settings_notification_set_vibration_strength(uint8_t level);
void watch_settings_notification_set_notification_vibration_strength(uint8_t level);
/**
* @brief
*
* @param duration
*/
void watch_settings_notification_set_vibration_duration(uint8_t duration);
void watch_settings_notification_set_notification_vibration_duration(uint8_t duration);
/**
* @brief
*
* @param enabled
*/
void watch_settings_notification_set_call_enabled(bool enabled);
/**
* @brief
*
* @param level
*/
void watch_settings_notification_set_call_vibration_strength(uint8_t level);
/**
* @brief
*
* @param duration
*/
void watch_settings_notification_set_call_vibration_duration(uint8_t duration);
/**
* @brief

View File

@ -50,6 +50,7 @@ void tls_set_rtc(struct tm *tblock)
ctrl2 = 0;
ctrl2 |= tblock->tm_mon;
tblock->tm_year -= 100;
ctrl2 |= tblock->tm_year << 8;
tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
@ -75,6 +76,7 @@ void tls_get_rtc(struct tm *tblock)
ctrl1 = tls_reg_read32(HR_PMU_RTC_CTRL1);
ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);
tblock->tm_year = ((int)((int)ctrl2 & 0x00007f00) >> 8);
tblock->tm_year += 100;
tblock->tm_mon = (ctrl2 & 0x0000000f);
tblock->tm_mday = (ctrl1 & 0x1f000000) >> 24;
tblock->tm_hour = (ctrl1 & 0x001f0000) >> 16;

View File

@ -49,6 +49,7 @@ INCLUDES += -I $(TOP_DIR)/app/app_drivers/lcd
INCLUDES += -I $(TOP_DIR)/app/app_drivers/mmc_sdio
INCLUDES += -I $(TOP_DIR)/app/app_drivers/i2c
INCLUDES += -I $(TOP_DIR)/app/app_drivers/watch_peripherals
INCLUDES += -I $(TOP_DIR)/app/app_drivers/watch_power_management
INCLUDES += -I $(TOP_DIR)/app/app_include
INCLUDES += -I $(TOP_DIR)/app/ble
INCLUDES += -I $(TOP_DIR)/app/app_utils

View File

@ -312,7 +312,7 @@ void music_player_screen_create(MusicPlayerScreen_t * const musicPlayerScreen)
lv_obj_set_style_text_font(musicPlayerScreen->playPauseBtn.label, &lv_font_montserrat_30, LV_PART_MAIN);
lv_obj_center(musicPlayerScreen->playPauseBtn.label);
lv_obj_set_user_data(musicPlayerScreen->playPauseBtn.button, MUSIC_CONTROL_PLAY);
lv_obj_set_user_data(musicPlayerScreen->playPauseBtn.button, (void *)MUSIC_CONTROL_PLAY);
lv_obj_add_event_cb(musicPlayerScreen->playPauseBtn.button, &(music_player_button_click_event_cb), LV_EVENT_CLICKED, musicPlayerScreen);
//Previous track button

View File

@ -108,8 +108,8 @@ void notification_screen_notify(NotificationScreen_t * const notificationScreen,
case NOTIFICATION_TYPE_CALL:
break;
default:
_display_message_notification(notificationScreen, notification);
if(notificationScreen->notificationOnStateChangeCb) notificationScreen->notificationOnStateChangeCb(NOTIFICATION_STATE_DISPLAYED);
_display_message_notification(notificationScreen, notification);
}
}

View File

@ -14,7 +14,7 @@ static const char *date_format = "dd/mm/yyyy\ndd/mm/yy\nyyyy/mm/dd\nyy/mm/dd";
static const char *timeout_options = "Off\n5 seconds\n10 seconds\n15 seconds\n20 seconds\n25 seconds\n30 seconds\n35 seconds\n40 seconds\n45 seconds\n50 seconds\n55 seconds\n60 seconds";
static const char *orientation_format = "Default\n90<EFBFBD>\n180<EFBFBD>\n270<EFBFBD>";
static const char* vibration_duration = "None\n100 ms\n150 ms\n200 ms\n250 ms\n300 ms\n350 ms\n400 ms";
static const char* vibration_force = "1\n2\n3\n4\n5\n6\n7\n8";
static const char* vibration_strength = "1\n2\n3\n4\n5\n6\n7\n8";
static const char* language_options = "Francais\nDeutsch\nEnglish";
@ -302,43 +302,93 @@ static void load_display_side_screen(SettingsScreen_t *settingsScreen)
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Duration");
lv_obj_align_to(label, on_touch_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, on_touch_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
lv_obj_t *on_touch_vibration_strength_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_strength_roller, on_touch_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_strength_roller, vibration_force, LV_ROLLER_MODE_NORMAL);
lv_roller_set_options(on_touch_vibration_strength_roller, vibration_strength, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_touch_vibration_strength_roller, 2);
lv_obj_set_width(on_touch_vibration_strength_roller, lv_obj_get_width(on_touch_vibration_duration_roller));
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Strength");
lv_obj_align_to(label, on_touch_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, on_touch_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
static void load_notifications_side_screen(SettingsScreen_t *settingsScreen)
{
lv_obj_t *label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate on\nnotifications :");
// Notification enable switch
lv_obj_t *notification_enable_switch = lv_switch_create(settingsScreen->side_screen);
bool toggled = false;
//if(settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb)
//settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb(&toggled, SETTING_MODE_GET);
if(toggled)lv_obj_add_state(notification_enable_switch, LV_STATE_CHECKED);
//lv_obj_add_event_cb(notification_enable_switch, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
lv_obj_t *on_touch_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_touch_vibration_duration_roller, 2);
lv_obj_t * label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Notifications");
lv_obj_align_to(label, notification_enable_switch, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate on\nnotifications :");
lv_obj_align_to(label, notification_enable_switch, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_t *on_notification_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_notification_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_notification_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_notification_vibration_duration_roller, 2);
//lv_obj_add_event_cb(vibration_duration_roller, &(vibration_duration_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Duration");
lv_obj_align_to(label, on_touch_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_align_to(label, on_notification_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
lv_obj_t *on_touch_vibration_force_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_touch_vibration_force_roller, on_touch_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_touch_vibration_force_roller, vibration_force, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_touch_vibration_force_roller, 2);
lv_obj_set_width(on_touch_vibration_force_roller, lv_obj_get_width(on_touch_vibration_duration_roller));
lv_obj_t *on_notification_vibration_strength_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_notification_vibration_strength_roller, on_notification_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_notification_vibration_strength_roller, vibration_strength, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_notification_vibration_strength_roller, 2);
lv_obj_set_width(on_notification_vibration_strength_roller, lv_obj_get_width(on_notification_vibration_duration_roller));
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Force");
lv_obj_align_to(label, on_touch_vibration_force_roller, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_label_set_text_static(label, "Strength");
lv_obj_align_to(label, on_notification_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
// Call enable switch
lv_obj_t *call_enable_switch = lv_switch_create(settingsScreen->side_screen);
toggled = false;
//if(settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb)
//settingsScreen->settingsScreenAPIInterface.setWristTiltSettingsCb(&toggled, SETTING_MODE_GET);
if(toggled)lv_obj_add_state(call_enable_switch, LV_STATE_CHECKED);
lv_obj_align_to(call_enable_switch, on_notification_vibration_strength_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
//lv_obj_add_event_cb(notification_enable_switch, &(activation_switch_cb), LV_EVENT_VALUE_CHANGED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Calls");
lv_obj_align_to(label, call_enable_switch, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Vibrate on calls :");
lv_obj_align_to(label, call_enable_switch, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_obj_t *on_call_vibration_duration_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_call_vibration_duration_roller, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_call_vibration_duration_roller, vibration_duration, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_call_vibration_duration_roller, 2);
//lv_obj_add_event_cb(vibration_duration_roller, &(vibration_duration_roller_cb), LV_EVENT_RELEASED, settingsScreen);
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Duration");
lv_obj_align_to(label, on_call_vibration_duration_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
lv_obj_t *on_call_vibration_strength_roller = lv_roller_create(settingsScreen->side_screen);
lv_obj_align_to(on_call_vibration_strength_roller, on_call_vibration_duration_roller, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
lv_roller_set_options(on_call_vibration_strength_roller, vibration_strength, LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(on_call_vibration_strength_roller, 2);
lv_obj_set_width(on_call_vibration_strength_roller, lv_obj_get_width(on_call_vibration_duration_roller));
label = lv_label_create(settingsScreen->side_screen);
lv_label_set_text_static(label, "Strength");
lv_obj_align_to(label, on_call_vibration_strength_roller, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
static void load_connectivity_side_screen(SettingsScreen_t *settingsScreen)