From 4f03e28691caf63d471e4ce086afb1ff7d3e6bbf Mon Sep 17 00:00:00 2001 From: Th3maz1ng Date: Sun, 16 Mar 2025 21:01:35 +0100 Subject: [PATCH] wip, to be removed --- .../watch_peripherals/watch_peripherals.c | 43 ++- .../watch_peripherals/watch_peripherals.h | 10 + src/W800_SDK_v1.00.10/app/gfx/gfx_task.c | 3 +- src/W800_SDK_v1.00.10/app/gfx/watch_face.c | 56 +++- src/W800_SDK_v1.00.10/app/gfx/watch_face.h | 19 +- .../lv_port_win_codeblocks/main.c | 96 +++++- .../lv_port_win_codeblocks/settings_screen.c | 306 +++++++++++++++++- .../lv_port_win_codeblocks/settings_screen.h | 67 +++- .../lv_port_win_codeblocks/watch_face.c | 105 ++++-- .../lv_port_win_codeblocks/watch_face.h | 33 +- 10 files changed, 655 insertions(+), 83 deletions(-) diff --git a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c index be4559a..ae57bbc 100644 --- a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c +++ b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c @@ -46,8 +46,10 @@ static battery_controller_status_e _battery_fsm = BATTERY_CONTROLLER_STATUS_DISC static BatteryControllerStatusChangeCb_t _BatteryControllerStatusChangeCb = NULL; /* Wakeup source boolean */ -static bool _wakeup_is_io = false; -static bool _wakeup_is_timer = false; +static struct +{ + bool is_io:1, is_timer:1, is_rtc_alarm:1; +} _wakeup_src = {false, false, false}; /* BMA456 structure */ static struct @@ -187,17 +189,25 @@ typedef enum wakeup_source { WAKEUP_SOURCE_IO = 0, WAKEUP_SOURCE_TIMER, + WAKEUP_SOURCE_RTC_ALARM, } wakeup_source_e; static void pmu_wakeup_source_irq_cb(void *arg) { wakeup_source_e wakeup_source = (wakeup_source_e)arg; - if(wakeup_source == WAKEUP_SOURCE_IO) - _wakeup_is_io = true; - - if(wakeup_source == WAKEUP_SOURCE_TIMER) - _wakeup_is_timer = true; + switch(wakeup_source) + { + case WAKEUP_SOURCE_IO: + _wakeup_src.is_io = true; + break; + case WAKEUP_SOURCE_TIMER: + _wakeup_src.is_timer = true; + break; + case WAKEUP_SOURCE_RTC_ALARM: + _wakeup_src.is_rtc_alarm = true; + break; + } } static void watch_peripherals_io_init(void) @@ -226,6 +236,7 @@ static void watch_peripherals_io_init(void) /* We register the IRQs needed to determine the watch wake up source/reason */ tls_pmu_gpio_isr_register(&(pmu_wakeup_source_irq_cb), (void *)WAKEUP_SOURCE_IO); tls_pmu_timer0_isr_register(&(pmu_wakeup_source_irq_cb), (void *)WAKEUP_SOURCE_TIMER); + tls_rtc_isr_register(&(pmu_wakeup_source_irq_cb), (void *)WAKEUP_SOURCE_RTC_ALARM); } #ifndef CASE_RETURN_STR @@ -464,9 +475,9 @@ void watch_peripherals_set_orientation(LCDOrientation_e orientation) bool watch_peripherals_wakeup_source_is_user(void) { - if(_wakeup_is_io) + if(_wakeup_src.is_io) { - _wakeup_is_io = false; + _wakeup_src.is_io = false; return true; } return false; @@ -474,9 +485,19 @@ bool watch_peripherals_wakeup_source_is_user(void) bool watch_peripherals_wakeup_source_is_timer(void) { - if(_wakeup_is_timer) + if(_wakeup_src.is_timer) { - _wakeup_is_timer = false; + _wakeup_src.is_timer = false; + return true; + } + return false; +} + +bool watch_peripherals_wakeup_source_is_rtc_alarm(void) +{ + if(_wakeup_src.is_rtc_alarm) + { + _wakeup_src.is_rtc_alarm = false; return true; } return false; diff --git a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h index af0df7b..d6187df 100644 --- a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h +++ b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h @@ -142,6 +142,7 @@ void watch_peripherals_set_orientation(LCDOrientation_e orientation); /** * @brief Check if the watch woke up because of the user(trigger on the wakeup pin : wrist tilt or touch screen). + * Calling this function clears the wakeup source flag. * * @return true if the source of the wakeup is the user * @return false otherwise @@ -150,12 +151,21 @@ bool watch_peripherals_wakeup_source_is_user(void); /** * @brief Check if the watch woke up because of a timed event (timer 0 of the PMU module). + * Calling this function clears the wakeup source flag. * * @return true if the source of the wake up is the timer 0 * @return false otherwise */ bool watch_peripherals_wakeup_source_is_timer(void); +/** + * @brief Check if the watch woke up because of a RTC alarm event. + * Calling this function clears the wakeup source flag. + * @return true if the source of the wake up is the RTC alarm + * @return false otherwise + */ +bool watch_peripherals_wakeup_source_is_rtc_alarm(void); + bool watch_peripherals_magnetometer_init(void); void watch_peripherals_magnetometer_calibration_data_set( diff --git a/src/W800_SDK_v1.00.10/app/gfx/gfx_task.c b/src/W800_SDK_v1.00.10/app/gfx/gfx_task.c index b5aba3a..e934328 100644 --- a/src/W800_SDK_v1.00.10/app/gfx/gfx_task.c +++ b/src/W800_SDK_v1.00.10/app/gfx/gfx_task.c @@ -817,7 +817,8 @@ void gfx_task(void *param) watch_face_register_step_counter_indicator_cb(&watchFace, &(step_count_cb)); watch_face_create(&watchFace); - lv_scr_load(watchFace.display); + /* Using this function to load the first screen allows to free the default screen obj */ + lv_scr_load_anim(watchFace.display, LV_SCR_LOAD_ANIM_NONE, 0U, 0U, true); //QMC5883L_set_calibration_data(-900, 2500, -1400, 1400, 2300, 7500, 0.0); diff --git a/src/W800_SDK_v1.00.10/app/gfx/watch_face.c b/src/W800_SDK_v1.00.10/app/gfx/watch_face.c index 6899a72..f13ea4f 100644 --- a/src/W800_SDK_v1.00.10/app/gfx/watch_face.c +++ b/src/W800_SDK_v1.00.10/app/gfx/watch_face.c @@ -99,6 +99,8 @@ static void gesture_event_cb(lv_event_t *e) // We delete the timer lv_timer_del(watchFace->batteryIndicator.lowBatteryAnimationTimer); lv_timer_del(watchFace->handAnimationTimer); + // Checking if timer is not NULL here because it could have been deleted already + if(watchFace->handHideTimer)lv_timer_del(watchFace->handHideTimer); lv_timer_del(watchFace->stepCounterRefreshTimer); // We create the menu screen and switch to it extern MenuScreen_t menuScreen; @@ -227,6 +229,13 @@ static void set_battery_state_icon(WatchFace_t * const watchFace) break; } } +static void hide_hour_and_minutes_hand_timer_cb(lv_timer_t *timer) +{ + WatchFace_t *watchFace = timer->user_data; + watchFace->handHideTimer = NULL; + + watch_face_show_hour_and_minute_hands(watchFace, true); +} static void hide_hour_and_minutes_hand_cb(lv_event_t *e) { @@ -234,13 +243,28 @@ static void hide_hour_and_minutes_hand_cb(lv_event_t *e) if(lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) { - lv_obj_clear_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); + if(watchFace->handHideTimer) + { + /* Make the timer execute now to re-display hands + and cleanly free the timer */ + lv_timer_ready(watchFace->handHideTimer); + } } else { - lv_obj_add_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); + // Let's hide the hands + watch_face_show_hour_and_minute_hands(watchFace, false); + + // Let's start the hand hide timer + if(watchFace->handHideTimer) + { + LV_LOG_ERROR("handHideTimer should be NULL here !"); + lv_timer_del(watchFace->handHideTimer); + watchFace->handHideTimer = NULL; + } + watchFace->handHideTimer = lv_timer_create(&(hide_hour_and_minutes_hand_timer_cb), 3000, watchFace); + // After the timer expires once, delete it by setting the repeat count to 1 + lv_timer_set_repeat_count(watchFace->handHideTimer, 1); } } @@ -584,6 +608,7 @@ void watch_face_destroy(WatchFace_t * const watchFace) watchFace->display = NULL; watchFace->handAnimationTimer = NULL; + watchFace->handHideTimer = NULL; watchFace->stepCounterRefreshTimer = NULL; watchFace->dateWindow.dateWindowWidget = NULL; watchFace->hourHand.handImg = NULL; @@ -611,6 +636,29 @@ void watch_face_force_sync(WatchFace_t *const watchFace) update_watch_hands_angles(watchFace, 0); } +void watch_face_show_hour_and_minute_hands(WatchFace_t * const watchFace, bool show) +{ + if(!watchFace) + { + LV_LOG_ERROR("NULL pointer given !"); + return; + } + + if(watch_face_is_in_use(watchFace)) + { + if(show && lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) + { + lv_obj_clear_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); + lv_obj_clear_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); + } + else if(!show && !lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) + { + lv_obj_add_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); + } + } +} + bool watch_face_is_in_use(WatchFace_t * const watchFace) { if(!watchFace) diff --git a/src/W800_SDK_v1.00.10/app/gfx/watch_face.h b/src/W800_SDK_v1.00.10/app/gfx/watch_face.h index b566e9f..27f3697 100644 --- a/src/W800_SDK_v1.00.10/app/gfx/watch_face.h +++ b/src/W800_SDK_v1.00.10/app/gfx/watch_face.h @@ -69,7 +69,9 @@ typedef struct WatchFace WatchHand_t minuteHand; WatchHand_t secondHand; WatchHand_t mediumHand24h; - lv_timer_t *handAnimationTimer, *stepCounterRefreshTimer; + lv_timer_t *handAnimationTimer; + lv_timer_t *stepCounterRefreshTimer; + lv_timer_t *handHideTimer; lv_obj_t *display; DateWindow_t dateWindow; BatteryIndicator_t batteryIndicator; @@ -119,13 +121,6 @@ void watch_face_register_step_counter_indicator_cb(WatchFace_t * const watchFace */ void watch_face_create(WatchFace_t * const watchFace); -/** - * @brief Sets the battery indicator to the given value in percent. - * - * @param watchFace a pointer to the watch face context structure. - * @param percentage the value to set the indicator to in percent. - */ - /** * @brief Sets the battery level in percent as well as it's current state to draw on the watch face. * @@ -158,6 +153,14 @@ void watch_face_set_step_count_indicator(WatchFace_t * const watchFace, uint32_t */ void watch_face_force_sync(WatchFace_t * const watchFace); +/** + * @brief Show or hide the hour and minute hand on the watch face. + * + * @param watchFace a pointer to the watch face context structure. + * @param show a boolean value indicating if hands should be shown or not. + */ +void watch_face_show_hour_and_minute_hands(WatchFace_t * const watchFace, bool show); + /** * @brief Returns true if the watch face screen is currently being used and displayed. * diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/main.c b/src/lvgl_win_sim/lv_port_win_codeblocks/main.c index 5699098..16e8401 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/main.c +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/main.c @@ -148,10 +148,99 @@ static uint32_t musicPlayerTimeRefmsCb(void) return ms_time; } +static void setTimeCb(uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *day, uint8_t *month, uint8_t *year, SettingMode_e mode) +{ + struct tm timeToSet; + + //First we get the current time from the RTC + time_t time_type = time(NULL); + memcpy(&timeToSet, localtime(&time_type), sizeof timeToSet); + + if(SETTING_MODE_GET == mode) + { + *hour = timeToSet.tm_hour; + *minute = timeToSet.tm_min; + *second = timeToSet.tm_sec; + *day = timeToSet.tm_mday; + *month = timeToSet.tm_mon; + *year = timeToSet.tm_year; + } +} + +static void getBatteryVoltageCb(uint16_t *battery_voltage) +{ + static uint16_t bat_vol = 0; + bat_vol += 12; + bat_vol %= 4200; + *battery_voltage = bat_vol; +} + +static void getMagnetometerRawDataCb(int16_t *field_x, int16_t *field_y, int16_t *field_z, float *temperature) +{ + static int16_t x = -235, y = 1522, z = 65; + static float temp = 15.42f; + x += 15; + y -= 12; + z += 19; + + *field_x = x; + *field_y = y; + *field_z = z; + + temp += 0.04f; if(temp > 35) temp = 15.42f; + *temperature = temp; +} + +static void getAccelerometerRawDataCb(int16_t *accel_x, int16_t *accel_y, int16_t *accel_z, float *temperature, uint32_t *step_count) +{ + static int16_t x = 665, y = -25, z = 1245; + static uint32_t steps = 666U; + static float temp = 15.42f; + x += 15; + y -= 12; + z -= 19; + if(accel_x && accel_y && accel_z) + { + *accel_x = x; + *accel_y = y; + *accel_z = z; + } + + + temp += 0.04f; if(temp > 35) temp = 15.42f; + if(temperature) + *temperature = temp; + + steps += 1; + if(step_count) + *step_count = steps; +} + +static void getBMP280DataCb(float *temperature, float *pressure) +{ + /* We want hPa's */ + static float temp = 15.42f, press = 981.42f; + temp += 0.26f; if(temp > 35) temp = 15.42f; + press += 1.42f;if(press > 1045) press = 981.42f; + + *temperature = temp; + *pressure = press; +} + WatchFace_t watchFace; MenuScreen_t menuScreen; CompassScreen_t compassScreen; + SettingsScreen_t settingsScreen; +SettingsScreenAPIInterface_t settingsScreenAPIInterface = +{ + .setTimeSettingsCb = &(setTimeCb), + .getBatteryVoltageCb = &(getBatteryVoltageCb), + .getMagnetometerRawDataCb = &(getMagnetometerRawDataCb), + .getAccelerometerRawDataCb = &(getAccelerometerRawDataCb), + .getBMP280DataCb = &(getBMP280DataCb), +}; + AltimeterScreen_t altimeterScreen; FindMyPhoneScreen_t findMyPhoneScreen; MusicPlayerScreen_t musicPlayerScreen; @@ -183,6 +272,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLi compass_screen_register_on_state_change_cb(&compassScreen, &(compass_screen_on_state_change_cb)); compass_screen_register_azimuth_and_temperature_cb(&compassScreen, &(azimuth_and_temperature_cb)); settings_screen_init(&settingsScreen); + settings_screen_register_API_interface(&settingsScreen, &settingsScreenAPIInterface); altimeter_screen_init(&altimeterScreen); altimeter_screen_register_on_state_change_cb(&altimeterScreen, &(alti_on_state_change_cb)); altimeter_screen_register_measurement_cb(&altimeterScreen, &(alti_meas_cb)); @@ -207,15 +297,15 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLi watch_face_register_date_time_cb(&watchFace, &(date_time_cb)); watch_face_create(&watchFace); - lv_scr_load(watchFace.display); - + lv_scr_load_anim(watchFace.display, LV_SCR_LOAD_ANIM_NONE, 0, 0, true); watch_face_set_step_count_indicator(&watchFace, 10258); //settings_screen(); //watch_face(); - while(!lv_win32_quit_signal) { + while(!lv_win32_quit_signal) + { /* Periodically call the lv_task handler. * It could be done in a timer interrupt or an OS task too.*/ lv_task_handler(); diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.c b/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.c index 2d6cca2..14f1284 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.c +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.c @@ -1,3 +1,5 @@ +#include +#include #include "lvgl.h" #include "common_screen_components.h" #include "settings_screen.h" @@ -29,6 +31,14 @@ static void _reset_switch_pointers(SettingsScreen_t * const settingsScreen) 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); +/* Helper functions used to update sensor label data */ +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_to_label(SettingsScreen_t * const settingsScreen); +static void _set_accelerometer_axes_to_label(SettingsScreen_t * const settingsScreen); +static void _set_accelerometer_steps_and_temperature_to_label(SettingsScreen_t * const settingsScreen); +static void _set_pressure_sensor_to_label(SettingsScreen_t * const settingsScreen); + static void gesture_event_cb(lv_event_t *e) { SettingsScreen_t *settingsScreen = e->user_data; @@ -43,6 +53,7 @@ static void gesture_event_cb(lv_event_t *e) LV_LOG_USER("GESTURE : RIGHT"); // We delete the timer if it was created if(settingsScreen->about_refresh_timer)lv_timer_del(settingsScreen->about_refresh_timer); + if(settingsScreen->sensors_refresh_timer)lv_timer_del(settingsScreen->sensors_refresh_timer); // We create the menu screen and switch to it extern MenuScreen_t menuScreen; menu_screen_create(&menuScreen); @@ -159,9 +170,40 @@ static void about_refresh_timer_cb(lv_timer_t *timer) { SettingsScreen_t *settingsScreen = timer->user_data; + time_t time_type = time(NULL); + struct tm *tm = localtime(&time_type); + + snprintf(settingsScreen->currentTime.current_time_text, sizeof settingsScreen->currentTime.current_time_text, "%s%u:%s%u:%s%u %s%u/%s%u/%u", + tm->tm_hour < 10 ? "0":"", tm->tm_hour, + tm->tm_min < 10 ? "0":"", tm->tm_min, + tm->tm_sec < 10 ? "0":"", tm->tm_sec, + tm->tm_mday < 10 ? "0":"", tm->tm_mday, + tm->tm_mon + 1 < 10 ? "0":"", tm->tm_mon + 1, + tm->tm_year+1900); lv_label_set_text_static(settingsScreen->currentTime.current_time_label, settingsScreen->currentTime.current_time_text); } +static void sensors_refresh_timer_cb(lv_timer_t *timer) +{ + SettingsScreen_t *settingsScreen = timer->user_data; + + /* Timer callback is called every 150 ms, + some data don't need that update rate */ + static uint8_t timer_divider = 6; + + if(timer_divider++ == 6) + { + _set_rtc_time_to_label(settingsScreen); + _set_battery_voltage_to_label(settingsScreen); + _set_pressure_sensor_to_label(settingsScreen); + _set_accelerometer_steps_and_temperature_to_label(settingsScreen); + timer_divider = 0; + } + + _set_magnetometer_to_label(settingsScreen); + _set_accelerometer_axes_to_label(settingsScreen); +} + static void load_time_and_date_side_screen(SettingsScreen_t *settingsScreen) { lv_obj_t *label = lv_label_create(settingsScreen->side_screen); @@ -451,6 +493,125 @@ static void load_connectivity_side_screen(SettingsScreen_t *settingsScreen) lv_obj_align_to(settingsScreen->wifi_label, settingsScreen->wifi_switch, LV_ALIGN_OUT_RIGHT_MID, 10, 0); } +static void load_sensors_side_screen(SettingsScreen_t *settingsScreen) +{ + lv_obj_t *label = lv_label_create(settingsScreen->side_screen); + lv_label_set_text_static(label, "Sensors :"); + /* First, display the RTC time */ + lv_obj_t *rtc_time = lv_label_create(settingsScreen->side_screen); + lv_label_set_text_static(rtc_time, "Clock :"); + lv_obj_align_to(rtc_time, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10); + + settingsScreen->sensors_labels.clock.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.clock.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.clock.label, rtc_time, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); + _set_rtc_time_to_label(settingsScreen); + + /* Let's display the magnetometer data */ + lv_obj_t *magnetometer_data = lv_label_create(settingsScreen->side_screen); + lv_label_set_text_static(magnetometer_data, "Magnetometer :"); + lv_obj_align_to(magnetometer_data, settingsScreen->sensors_labels.clock.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10); + + settingsScreen->sensors_labels.magnetometer.x.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.magnetometer.x.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.magnetometer.x.label, magnetometer_data, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.magnetometer.y.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.magnetometer.y.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.magnetometer.y.label, settingsScreen->sensors_labels.magnetometer.x.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.magnetometer.z.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.magnetometer.z.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.magnetometer.z.label, settingsScreen->sensors_labels.magnetometer.y.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.magnetometer.temperature.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.magnetometer.temperature.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.magnetometer.temperature.label, settingsScreen->sensors_labels.magnetometer.z.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + _set_magnetometer_to_label(settingsScreen); + + lv_obj_update_layout(settingsScreen->sensors_labels.magnetometer.temperature.label); + + lv_obj_t *magnetometer_cal_btn = lv_btn_create(settingsScreen->side_screen); + lv_obj_align(magnetometer_cal_btn, LV_ALIGN_TOP_MID, 0, lv_obj_get_y(settingsScreen->sensors_labels.magnetometer.temperature.label) + lv_obj_get_height(settingsScreen->sensors_labels.magnetometer.temperature.label) + 3); + + lv_obj_t *magnetometer_cal_btn_label = lv_label_create(magnetometer_cal_btn); + lv_label_set_text_static(magnetometer_cal_btn_label, "Calibrate"); + lv_obj_center(magnetometer_cal_btn_label); + + lv_obj_update_layout(magnetometer_cal_btn); + + /* Let's display the accelerometer data */ + lv_obj_t *accelerometer_data = lv_label_create(settingsScreen->side_screen); + lv_label_set_text_static(accelerometer_data, "Accelerometer :"); + lv_obj_align(accelerometer_data, LV_ALIGN_TOP_LEFT, 0, lv_obj_get_y(magnetometer_cal_btn) + lv_obj_get_height(magnetometer_cal_btn) + 10); + + settingsScreen->sensors_labels.accelerometer.x.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.accelerometer.x.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.accelerometer.x.label, accelerometer_data, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.accelerometer.y.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.accelerometer.y.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.accelerometer.y.label, settingsScreen->sensors_labels.accelerometer.x.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.accelerometer.z.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.accelerometer.z.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.accelerometer.z.label, settingsScreen->sensors_labels.accelerometer.y.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.accelerometer.temperature.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.accelerometer.temperature.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.accelerometer.temperature.label, settingsScreen->sensors_labels.accelerometer.z.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.accelerometer.steps.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.accelerometer.steps.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.accelerometer.steps.label, settingsScreen->sensors_labels.accelerometer.temperature.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + _set_accelerometer_axes_to_label(settingsScreen); + _set_accelerometer_steps_and_temperature_to_label(settingsScreen); + + lv_obj_update_layout(settingsScreen->sensors_labels.accelerometer.steps.label); + + lv_obj_t *accelerometer_cal_btn = lv_btn_create(settingsScreen->side_screen); + lv_obj_align(accelerometer_cal_btn, LV_ALIGN_TOP_MID, 0, lv_obj_get_y(settingsScreen->sensors_labels.accelerometer.steps.label) + lv_obj_get_height(settingsScreen->sensors_labels.accelerometer.steps.label) + 3); + + lv_obj_t *accelerometer_cal_btn_label = lv_label_create(accelerometer_cal_btn); + lv_label_set_text_static(accelerometer_cal_btn_label, "Calibrate"); + lv_obj_center(accelerometer_cal_btn_label); + + lv_obj_update_layout(accelerometer_cal_btn); + + /* Let's display the pressure sensor data */ + lv_obj_t *bmp280_data = lv_label_create(settingsScreen->side_screen); + lv_label_set_text_static(bmp280_data, "Pressure &\ntemperature :"); + lv_obj_align(bmp280_data, LV_ALIGN_TOP_LEFT, 0, lv_obj_get_y(accelerometer_cal_btn) + lv_obj_get_height(accelerometer_cal_btn) + 10); + + settingsScreen->sensors_labels.pressure.pressure.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.pressure.pressure.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.pressure.pressure.label, bmp280_data, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + + settingsScreen->sensors_labels.pressure.temperature.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.pressure.temperature.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.pressure.temperature.label, settingsScreen->sensors_labels.pressure.pressure.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + _set_pressure_sensor_to_label(settingsScreen); + + /* Let's display the battery voltage */ + lv_obj_t *battery_label = lv_label_create(settingsScreen->side_screen); + lv_label_set_text_static(battery_label, "Battery Voltage :"); + lv_obj_align_to(battery_label, settingsScreen->sensors_labels.pressure.temperature.label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10); + + settingsScreen->sensors_labels.battery_voltage.label = lv_label_create(settingsScreen->side_screen); + lv_obj_set_style_text_color(settingsScreen->sensors_labels.battery_voltage.label, lv_color_make(130, 130, 130), LV_PART_MAIN); + lv_obj_align_to(settingsScreen->sensors_labels.battery_voltage.label, battery_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); + _set_battery_voltage_to_label(settingsScreen); + + /* Create and start the refresh timer */ + if(settingsScreen->sensors_refresh_timer) + { + LV_LOG_ERROR("sensors_refresh_timer should be NULL here !"); + lv_timer_del(settingsScreen->sensors_refresh_timer); + settingsScreen->sensors_refresh_timer = NULL; + } + settingsScreen->sensors_refresh_timer = lv_timer_create(&(sensors_refresh_timer_cb), 150, settingsScreen); +} + static void load_language_side_screen(SettingsScreen_t *settingsScreen) { lv_obj_t *label = lv_label_create(settingsScreen->side_screen); @@ -534,7 +695,7 @@ static void load_about_side_screen(SettingsScreen_t *settingsScreen) lv_obj_align_to(bmp280_pressure, bmp280_temperature, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3); lv_obj_t *battery_label = lv_label_create(settingsScreen->side_screen); - lv_label_set_text_static(battery_label, "Battery Voltage :"); + lv_label_set_text_static(battery_label, "Battery voltage :"); lv_obj_align_to(battery_label, bmp280_pressure, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); lv_obj_t *battery_voltage = lv_label_create(settingsScreen->side_screen); @@ -678,15 +839,16 @@ void settings_screen_destroy(SettingsScreen_t * const settingsScreen) settingsScreen->settingsScreenOnStateChangeCb(SETTINGS_SCREEN_STATE_CLOSED, (SettingsScreenCategory_e)lv_obj_get_user_data(settingsScreen->last_selected_item)); } - settingsScreen->hour_roller = NULL; - settingsScreen->minute_roller = NULL; - settingsScreen->second_roller = NULL; - settingsScreen->day_roller = NULL; - settingsScreen->month_roller = NULL; - settingsScreen->year_roller = NULL; - settingsScreen->display = NULL; - settingsScreen->about_refresh_timer = NULL; - settingsScreen->last_selected_item = NULL; + settingsScreen->hour_roller = NULL; + settingsScreen->minute_roller = NULL; + settingsScreen->second_roller = NULL; + settingsScreen->day_roller = NULL; + settingsScreen->month_roller = NULL; + settingsScreen->year_roller = NULL; + settingsScreen->display = NULL; + settingsScreen->about_refresh_timer = NULL; + settingsScreen->sensors_refresh_timer = NULL; + settingsScreen->last_selected_item = NULL; } static void _simulate_side_screen_item_click(SettingsScreen_t * const settingsScreen, lv_obj_t *item) @@ -699,6 +861,12 @@ static void _simulate_side_screen_item_click(SettingsScreen_t * const settingsSc settingsScreen->about_refresh_timer = NULL; } + if(settingsScreen->last_selected_item == settingsScreen->sensors_item) + { + lv_timer_del(settingsScreen->sensors_refresh_timer); + settingsScreen->sensors_refresh_timer = NULL; + } + // Updating the background of the selected category lv_obj_set_style_bg_color(item, lv_color_make(178, 223, 219), LV_PART_MAIN); if(settingsScreen->last_selected_item) @@ -735,6 +903,10 @@ static void _simulate_side_screen_item_click(SettingsScreen_t * const settingsSc { load_connectivity_side_screen(settingsScreen); } + else if(item == settingsScreen->sensors_item) + { + load_sensors_side_screen(settingsScreen); + } else if(item == settingsScreen->language_item) { load_language_side_screen(settingsScreen); @@ -745,6 +917,120 @@ static void _simulate_side_screen_item_click(SettingsScreen_t * const settingsSc } } +static void _set_rtc_time_to_label(SettingsScreen_t * const settingsScreen) +{ + uint8_t hour = 0U, minute = 0U, second = 0U, day = 0U, month = 0U, year = 0U; + if(settingsScreen->settingsScreenAPIInterface.setTimeSettingsCb) + settingsScreen->settingsScreenAPIInterface.setTimeSettingsCb(&hour, &minute, &second, &day, &month, &year, SETTING_MODE_GET); + sprintf(settingsScreen->sensors_labels.clock.text, "%s%u:%s%u:%s%u %s%u/%s%u/%u", + hour < 10 ? "0":"", hour, + minute < 10 ? "0":"", minute, + second < 10 ? "0":"", second, + day < 10 ? "0":"", day, + month + 1 < 10 ? "0":"", month + 1, + year+1900); + + lv_label_set_text_static(settingsScreen->sensors_labels.clock.label, settingsScreen->sensors_labels.clock.text); +} + +static void _set_battery_voltage_to_label(SettingsScreen_t * const settingsScreen) +{ + uint16_t voltage = 0; + if(settingsScreen->settingsScreenAPIInterface.getBatteryVoltageCb) settingsScreen->settingsScreenAPIInterface.getBatteryVoltageCb(&voltage); + + sprintf(settingsScreen->sensors_labels.battery_voltage.text, "%u mV", voltage); + + lv_label_set_text_static(settingsScreen->sensors_labels.battery_voltage.label, settingsScreen->sensors_labels.battery_voltage.text); +} + +static void _set_magnetometer_to_label(SettingsScreen_t * const settingsScreen) +{ + int16_t field_x = 0, field_y = 0, field_z = 0; + float temperature = 0.0f; + + if(settingsScreen->settingsScreenAPIInterface.getMagnetometerRawDataCb) + settingsScreen->settingsScreenAPIInterface.getMagnetometerRawDataCb(&field_x, + &field_y, + &field_z, + &temperature); + snprintf(settingsScreen->sensors_labels.magnetometer.x.text, + sizeof(settingsScreen->sensors_labels.magnetometer.x.text)-1, + "x: %d", field_x); + snprintf(settingsScreen->sensors_labels.magnetometer.y.text, + sizeof(settingsScreen->sensors_labels.magnetometer.y.text)-1, + "y: %d", field_y); + snprintf(settingsScreen->sensors_labels.magnetometer.z.text, + sizeof(settingsScreen->sensors_labels.magnetometer.z.text)-1, + "z: %d", field_z); + snprintf(settingsScreen->sensors_labels.magnetometer.temperature.text, + sizeof(settingsScreen->sensors_labels.magnetometer.temperature.text)-1, + "%.2f °C", temperature); + + lv_label_set_text_static(settingsScreen->sensors_labels.magnetometer.x.label, settingsScreen->sensors_labels.magnetometer.x.text); + lv_label_set_text_static(settingsScreen->sensors_labels.magnetometer.y.label, settingsScreen->sensors_labels.magnetometer.y.text); + lv_label_set_text_static(settingsScreen->sensors_labels.magnetometer.z.label, settingsScreen->sensors_labels.magnetometer.z.text); + lv_label_set_text_static(settingsScreen->sensors_labels.magnetometer.temperature.label, settingsScreen->sensors_labels.magnetometer.temperature.text); +} + +static void _set_accelerometer_axes_to_label(SettingsScreen_t * const settingsScreen) +{ + int16_t accel_x = 0, accel_y = 0, accel_z = 0; + + if(settingsScreen->settingsScreenAPIInterface.getAccelerometerRawDataCb) + settingsScreen->settingsScreenAPIInterface.getAccelerometerRawDataCb(&accel_x, + &accel_y, + &accel_z, + NULL, + NULL); + snprintf(settingsScreen->sensors_labels.accelerometer.x.text, + sizeof(settingsScreen->sensors_labels.accelerometer.x.text)-1, + "x: %d", accel_x); + snprintf(settingsScreen->sensors_labels.accelerometer.y.text, + sizeof(settingsScreen->sensors_labels.accelerometer.y.text)-1, + "y: %d", accel_y); + snprintf(settingsScreen->sensors_labels.accelerometer.z.text, + sizeof(settingsScreen->sensors_labels.accelerometer.z.text)-1, + "z: %d", accel_z); + + lv_label_set_text_static(settingsScreen->sensors_labels.accelerometer.x.label, settingsScreen->sensors_labels.accelerometer.x.text); + lv_label_set_text_static(settingsScreen->sensors_labels.accelerometer.y.label, settingsScreen->sensors_labels.accelerometer.y.text); + lv_label_set_text_static(settingsScreen->sensors_labels.accelerometer.z.label, settingsScreen->sensors_labels.accelerometer.z.text); +} + +static void _set_accelerometer_steps_and_temperature_to_label(SettingsScreen_t * const settingsScreen) +{ + float temperature = 0.0F; + uint32_t steps = 0U; + + if(settingsScreen->settingsScreenAPIInterface.getAccelerometerRawDataCb) + settingsScreen->settingsScreenAPIInterface.getAccelerometerRawDataCb(NULL, + NULL, + NULL, + &temperature, + &steps); + snprintf(settingsScreen->sensors_labels.accelerometer.temperature.text, + sizeof(settingsScreen->sensors_labels.accelerometer.temperature.text)-1, + "%.2f °C", temperature); + snprintf(settingsScreen->sensors_labels.accelerometer.steps.text, + sizeof(settingsScreen->sensors_labels.accelerometer.steps.text)-1, + "%s: %u", "steps", steps); + + lv_label_set_text_static(settingsScreen->sensors_labels.accelerometer.temperature.label, settingsScreen->sensors_labels.accelerometer.temperature.text); + lv_label_set_text_static(settingsScreen->sensors_labels.accelerometer.steps.label, settingsScreen->sensors_labels.accelerometer.steps.text); +} + +static void _set_pressure_sensor_to_label(SettingsScreen_t * const settingsScreen) +{ + float pressure = 0.0F, temperature = 0.0F; + if(settingsScreen->settingsScreenAPIInterface.getBMP280DataCb) settingsScreen->settingsScreenAPIInterface.getBMP280DataCb(&temperature, &pressure); + + snprintf(settingsScreen->sensors_labels.pressure.pressure.text, sizeof(settingsScreen->sensors_labels.pressure.pressure.text)-1, "%.2f hPa", pressure); + snprintf(settingsScreen->sensors_labels.pressure.temperature.text, sizeof(settingsScreen->sensors_labels.pressure.temperature.text)-1, "%.2f °C", temperature); + + lv_label_set_text_static(settingsScreen->sensors_labels.pressure.pressure.label, settingsScreen->sensors_labels.pressure.pressure.text); + lv_label_set_text_static(settingsScreen->sensors_labels.pressure.temperature.label, settingsScreen->sensors_labels.pressure.temperature.text); +} + static void _enable_time_and_date_rollers(bool enabled, SettingsScreen_t * const settingsScreen) { if(enabled) diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.h b/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.h index 08c421b..690b750 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.h +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/settings_screen.h @@ -3,9 +3,19 @@ #include "lvgl.h" +typedef enum SettingMode +{ + SETTING_MODE_GET = 0, + SETTING_MODE_SET +} SettingMode_e; + typedef struct SettingsScreenAPIInterface { - + void (*setTimeSettingsCb)(uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *day, uint8_t *month, uint8_t *year, SettingMode_e mode); + void (*getBatteryVoltageCb)(uint16_t *battery_voltage); + void (*getMagnetometerRawDataCb)(int16_t *field_x, int16_t *field_y, int16_t *field_z, float *temperature); + void (*getAccelerometerRawDataCb)(int16_t *accel_x, int16_t *accel_y, int16_t *accel_z, float *temperature, uint32_t *step_count); + void (*getBMP280DataCb)(float *temperature, float *pressure); } SettingsScreenAPIInterface_t; typedef enum SettingsScreenState @@ -61,6 +71,60 @@ typedef struct SettingsScreen lv_obj_t *ble_dev_name_value; lv_obj_t *ble_dev_mac_label; + struct + { + struct + { + lv_obj_t *label; + char text[20]; + } clock; + + struct + { + struct + { + lv_obj_t *label; + char text[11]; + } x, y, z, temperature; + } magnetometer; + + struct + { + struct + { + lv_obj_t *label; + char text[11]; + } x, y, z, temperature; + + struct + { + lv_obj_t *label; + char text[18]; + } steps; + } accelerometer; + + struct + { + struct + { + lv_obj_t *label; + char text[13]; + } pressure; + + struct + { + lv_obj_t *label; + char text[11]; + } temperature; + } pressure; + + struct + { + lv_obj_t *label; + char text[8]; + } battery_voltage; + } sensors_labels; + struct { lv_obj_t *current_time_label; @@ -84,6 +148,7 @@ typedef struct SettingsScreen /* Other */ lv_timer_t *about_refresh_timer; + lv_timer_t *sensors_refresh_timer; SettingsScreenOnStateChangeCb_t settingsScreenOnStateChangeCb; } SettingsScreen_t; diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.c b/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.c index bebdafd..1e42ac7 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.c +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.c @@ -89,9 +89,9 @@ static void _set_bluetooth_indicator(WatchFace_t * const watchFace) } } -static void gesture_event_cb(lv_event_t * e) +static void gesture_event_cb(lv_event_t *e) { - WatchFace_t *watchFace = e->user_data; + WatchFace_t *watchFace = lv_event_get_user_data(e); lv_dir_t gesture; switch(gesture = lv_indev_get_gesture_dir(lv_indev_get_act())) @@ -104,6 +104,8 @@ static void gesture_event_cb(lv_event_t * e) // We delete the timer lv_timer_del(watchFace->batteryIndicator.lowBatteryAnimationTimer); lv_timer_del(watchFace->handAnimationTimer); + // Checking if timer is not NULL here because it could have been deleted already + if(watchFace->handHideTimer)lv_timer_del(watchFace->handHideTimer); // We create the menu screen and switch to it extern MenuScreen_t menuScreen; menu_screen_create(&menuScreen); @@ -120,9 +122,9 @@ static void gesture_event_cb(lv_event_t * e) } } -static void cleanup_event_cb(lv_event_t * e) +static void cleanup_event_cb(lv_event_t *e) { - WatchFace_t *watchFace = e->user_data; + WatchFace_t *watchFace = lv_event_get_user_data(e); watch_face_destroy(watchFace); LV_LOG_USER("cleanup"); } @@ -163,7 +165,7 @@ static void update_watch_hands_angles(WatchFace_t * const watchFace, uint8_t inc watchFace->minuteHand.handAngle = 60 * watchFace->dateTime.tm_min + watchFace->secondHand.handAngle / 60; watchFace->hourHand.handAngle = 300 * watchFace->dateTime.tm_hour + watchFace->minuteHand.handAngle / 12; watchFace->mediumHand24h.handAngle = watchFace->hourHand.handAngle / 2; - LV_LOG_USER("angle : %f", watchFace->secondHand.handAngle); + //LV_LOG_USER("angle : %f", watchFace->secondHand.handAngle); //We update the angle lv_img_set_angle(watchFace->secondHand.handImg, (uint16_t) watchFace->secondHand.handAngle % 3600); @@ -241,34 +243,9 @@ static void set_battery_state_icon(WatchFace_t * const watchFace) } } -static void hide_hour_and_minutes_hand_cb(lv_event_t *e) +/* Just for testing purposes, creates a new notification */ +static void create_notification_cb(lv_event_t *e) { - WatchFace_t *watchFace = lv_event_get_user_data(e); - - // Consumes too much ram on embedded target :-( - /*if(255 == lv_obj_get_style_opa(watchFace->hourHand.handImg, LV_PART_MAIN)) - { - lv_obj_set_style_opa(watchFace->hourHand.handImg, 120, LV_PART_MAIN); - lv_obj_set_style_opa(watchFace->minuteHand.handImg, 120, LV_PART_MAIN); - } - else - { - lv_obj_set_style_opa(watchFace->hourHand.handImg, 255, LV_PART_MAIN); - lv_obj_set_style_opa(watchFace->minuteHand.handImg, 255, LV_PART_MAIN); - }*/ - - if(lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) - { - lv_obj_clear_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); - } - else - { - lv_obj_add_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); - } - - //Just for testing purposes, create a new notification char *title = malloc(strlen("JoeJohny John")+1); strcpy(title, "JoeJohny John"); @@ -284,6 +261,45 @@ to let you know what I do for me and you bro !"); LV_LOG_USER("unread(%u)/ total(%u)", notification_screen_unread_notification_count(¬ificationScreen), notification_screen_notification_count(¬ificationScreen)); } +static void hide_hour_and_minutes_hand_timer_cb(lv_timer_t *timer) +{ + WatchFace_t *watchFace = timer->user_data; + watchFace->handHideTimer = NULL; + + watch_face_show_hour_and_minute_hands(watchFace, true); +} + +static void hide_hour_and_minutes_hand_cb(lv_event_t *e) +{ + WatchFace_t *watchFace = lv_event_get_user_data(e); + + if(lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) + { + if(watchFace->handHideTimer) + { + /* Make the timer execute now to re-display hands + and cleanly free the timer */ + lv_timer_ready(watchFace->handHideTimer); + } + } + else + { + // Let's hide the hands + watch_face_show_hour_and_minute_hands(watchFace, false); + + // Let's start the hand hide timer + if(watchFace->handHideTimer) + { + LV_LOG_ERROR("handHideTimer should be NULL here !"); + lv_timer_del(watchFace->handHideTimer); + watchFace->handHideTimer = NULL; + } + watchFace->handHideTimer = lv_timer_create(&(hide_hour_and_minutes_hand_timer_cb), 3000, watchFace); + // After the timer expires once, delete it by setting the repeat count to 1 + lv_timer_set_repeat_count(watchFace->handHideTimer, 1); + } +} + void watch_face_init(WatchFace_t * const watchFace) { if(!watchFace) @@ -329,6 +345,7 @@ void watch_face_create(WatchFace_t * const watchFace) lv_img_set_src(watchFace->display, watch_face_img); lv_obj_set_style_bg_color(watchFace->display, lv_color_white(), LV_PART_MAIN); lv_obj_add_event_cb(watchFace->display, &(hide_hour_and_minutes_hand_cb), LV_EVENT_LONG_PRESSED, watchFace); + //lv_obj_add_event_cb(watchFace->display, &(create_notification_cb), LV_EVENT_LONG_PRESSED, NULL); //Battery arc is created here if(watchFace->batteryIndicator.batteryArc) @@ -593,6 +610,7 @@ void watch_face_destroy(WatchFace_t * const watchFace) watchFace->display = NULL; watchFace->handAnimationTimer = NULL; + watchFace->handHideTimer = NULL; watchFace->dateWindow.dateWindowWidget = NULL; watchFace->hourHand.handImg = NULL; watchFace->minuteHand.handImg = NULL; @@ -619,6 +637,29 @@ void watch_face_force_sync(WatchFace_t *const watchFace) update_watch_hands_angles(watchFace, 0); } +void watch_face_show_hour_and_minute_hands(WatchFace_t * const watchFace, bool show) +{ + if(!watchFace) + { + LV_LOG_ERROR("NULL pointer given !"); + return; + } + + if(watch_face_is_in_use(watchFace)) + { + if(show && lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) + { + lv_obj_clear_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); + lv_obj_clear_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); + } + else if(!show && !lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN)) + { + lv_obj_add_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN); + } + } +} + bool watch_face_is_in_use(WatchFace_t * const watchFace) { if(!watchFace) diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.h b/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.h index 63cdb07..9d14e27 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.h +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/watch_face.h @@ -68,6 +68,7 @@ typedef struct WatchFace WatchHand_t secondHand; WatchHand_t mediumHand24h; lv_timer_t *handAnimationTimer; + lv_timer_t *handHideTimer; lv_obj_t *display; DateWindow_t dateWindow; BatteryIndicator_t batteryIndicator; @@ -76,7 +77,12 @@ typedef struct WatchFace struct tm dateTime; } WatchFace_t; -/* Initializes the watch face context object */ +/** + * @brief Initializes the watch face context object + * @note This function has to be called first before any others + * + * @param watchFace a pointer to the watch face context structure to initialize. + */ void watch_face_init(WatchFace_t * const watchFace); /** @@ -103,13 +109,6 @@ void watch_face_register_battery_indicator_cb(WatchFace_t * const watchFace, Bat */ void watch_face_create(WatchFace_t * const watchFace); -/** - * @brief Sets the battery indicator to the given value in percent. - * - * @param watchFace a pointer to the watch face context structure. - * @param percentage the value to set the indicator to in percent. - */ - /** * @brief Sets the battery level in percent as well as it's current state to draw on the watch face. * @@ -129,31 +128,39 @@ void watch_face_set_bluetooth_indicator(WatchFace_t * const watchFace, Bluetooth /** * @brief Shows the current step count passed as parameter on the watch face. - * + * * @param watchFace a pointer to the watch face context structure. * @param step_count the step count to show on the watch face. */ void watch_face_set_step_count_indicator(WatchFace_t * const watchFace, uint32_t stepCount); /** - * @brief Forces the watch face to sync up with the RTC by calling the provided date_time_cb + * @brief Forces the watch face to sync up with the RTC by calling the provided date_time_cb. * * @param watchFace a pointer to the watch face context structure. */ void watch_face_force_sync(WatchFace_t * const watchFace); /** - * @brief Returns true if the watch face screen is currently being used and displayed. + * @brief Show or hide the hour and minute hand on the watch face. * * @param watchFace a pointer to the watch face context structure. - * @return true if the watch face screen is being used + * @param show a boolean value indicating if hands should be shown or not. + */ +void watch_face_show_hour_and_minute_hands(WatchFace_t * const watchFace, bool show); + +/** + * @brief Returns true if the watch face screen is currently being used and displayed. + * + * @param watchFace a pointer to the watch face context structure. + * @return true if the watch face screen is being used * @return false if the watch face screen is not being used/currently displayed */ bool watch_face_is_in_use(WatchFace_t * const watchFace); /** * @brief Frees all resources used by the WatchFace object. - * + * * @param watchFace a pointer to the watch face context structure. */ void watch_face_destroy(WatchFace_t * const watchFace);