wip, to be removed

This commit is contained in:
Th3maz1ng 2025-03-16 21:01:35 +01:00 committed by anschrammh
parent 4fd86d28ff
commit 61daa21de2
12 changed files with 688 additions and 93 deletions

View File

@ -1,3 +1,13 @@
/**
* @file QMC5883L.c
* @author Anatole SCHRAMM-HENRY
* @brief QMC5883L magnetometer functions implementation source file.
* @version 0.1
* @date 2025-03-17
*
* @copyright MIT
*/
#include <math.h>
#include "i2c.h"
#include "QMC5883L.h"
@ -45,18 +55,17 @@ bool QMC5883L_software_reset(void)
float QMC5883L_get_temperature(void)
{
uint8_t data;
uint8_t data[2];
int16_t raw_temp;
float temperature = 0.0F;
i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_TEMP_MSB_REG, &data);
if(i2c_read(QMC5883L_I2C_ADDR, QMC5883L_TEMP_LSB_REG, data, sizeof data))
{
raw_temp = (data[1] << 8) | data[0];
temperature = (float)raw_temp / 100.0F + _calibration_data.temperature_offset;
}
raw_temp = data << 8;
i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_TEMP_LSB_REG, &data);
raw_temp |= data;
return (float) raw_temp / 100.0 + _calibration_data.temperature_offset;
return temperature;
}
bool QMC5883L_is_data_available(void)

View File

@ -1,3 +1,13 @@
/**
* @file QMC5883L.h
* @author Anatole SCHRAMM-HENRY
* @brief QMC5883L magnetometer functions API header file.
* @version 0.1
* @date 2025-03-17
*
* @copyright MIT
*/
#ifndef QMC5883L_H
#define QMC5883L_H

View File

@ -13,6 +13,7 @@
#include "CST816D.h"
#include "app_utils.h"
#include "watch_settings.h"
#include "FreeRTOS.h"
#define INTERRUPT_POLICY (0)
#define POLL_POLICY (1)
@ -46,8 +47,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 +190,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 +237,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 +476,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 +486,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;
@ -591,7 +613,8 @@ bool watch_peripherals_pressure_sensor_select_profile(watch_peripherals_pressure
float watch_peripherals_pressure_sensor_get_pressure(float * const temperature)
{
BMP280_trigger_measurement();
/* Not great but needed to avoid an I2C wait ack err */
tls_os_time_delay(pdMS_TO_TICKS(2));
while(BMP280_is_measuring());
return BMP280_get_pressure(temperature);

View File

@ -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(

View File

@ -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);

View File

@ -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)

View File

@ -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.
*

View File

@ -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();

View File

@ -1,3 +1,5 @@
#include <stdio.h>
#include <time.h>
#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,122 @@ 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);
snprintf(settingsScreen->sensors_labels.clock.text,
sizeof(settingsScreen->sensors_labels.clock.text)-1, "%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);
snprintf(settingsScreen->sensors_labels.battery_voltage.text,
sizeof(settingsScreen->sensors_labels.battery_voltage.text)-1, "%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)

View File

@ -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;

View File

@ -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(&notificationScreen), notification_screen_notification_count(&notificationScreen));
}
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)

View File

@ -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);