From af71c44af454334b0324bb2c0c231a4240b2d692 Mon Sep 17 00:00:00 2001 From: anschrammh Date: Thu, 19 Oct 2023 08:10:32 +0200 Subject: [PATCH] The compass app now updates it's azimuth and temperature by itself with a timer and doesn't rely on the main loop to do so. It also, through a callback, put the magnetometer in active or standby mode to save power when leaving the app --- .../app/gfx/compass_screen.c | 58 +++++++++++++- .../app/gfx/compass_screen.h | 34 +++++++++ .../lv_port_win_codeblocks/compass_screen.c | 72 ++++++++++++++---- .../lv_port_win_codeblocks/compass_screen.h | 76 +++++++++++++++++-- 4 files changed, 220 insertions(+), 20 deletions(-) diff --git a/src/W800_SDK_v1.00.10/app/gfx/compass_screen.c b/src/W800_SDK_v1.00.10/app/gfx/compass_screen.c index a945c31..6d03f48 100644 --- a/src/W800_SDK_v1.00.10/app/gfx/compass_screen.c +++ b/src/W800_SDK_v1.00.10/app/gfx/compass_screen.c @@ -20,7 +20,6 @@ static const char *cardinals[] = static void gesture_event_cb(lv_event_t * e) { CompassScreen_t *compassScreen = e->user_data; - (void)compassScreen; lv_dir_t gesture; switch(gesture = lv_indev_get_gesture_dir(lv_indev_get_act())) @@ -30,6 +29,8 @@ static void gesture_event_cb(lv_event_t * e) break; case LV_DIR_RIGHT: LV_LOG_USER("GESTURE : RIGHT"); + // We delete the refresh timer + lv_timer_del(compassScreen->refreshTimer); // We create the menu screen and switch to it extern MenuScreen_t menuScreen; menu_screen_create(&menuScreen); @@ -53,6 +54,23 @@ static void cleanup_event_cb(lv_event_t * e) LV_LOG_USER("cleanup"); } +static void _compass_screen_refresh_timer_cb(lv_timer_t *timer) +{ + CompassScreen_t *compassScreen = timer->user_data; + + if(compassScreen->compassScreenAzimuthAndTemperatureCb) + { + uint16_t azimuth = 0; + float temperature = 0.0f; + bool refreshAzimuth = true, refreshTemperature = true; + + compassScreen->compassScreenAzimuthAndTemperatureCb(&azimuth, &refreshAzimuth, &temperature, &refreshTemperature); + + if(refreshAzimuth)compass_screen_set_azimuth(compassScreen, azimuth); + if(refreshTemperature)compass_screen_set_temperature(compassScreen, temperature); + } +} + static void create_cardinal(CompassCardinal_t *cardidanl, const char *cardinalText, lv_color_t textColor, lv_coord_t x, lv_coord_t y, lv_obj_t *parent) { cardidanl->label = lv_label_create(parent); @@ -93,6 +111,29 @@ void compass_screen_init(CompassScreen_t * const compassScreen) memset(compassScreen, 0, sizeof(CompassScreen_t)); strcpy(compassScreen->compassAzimuth.text, "0° N"); + strcpy(compassScreen->compassTemperature.text, "0.00°C"); +} + +void compass_screen_register_on_state_change_cb(CompassScreen_t * const compassScreen, CompassScreenOnStateChangeCb_t compassScreenOnStateChangeCb) +{ + if(!compassScreen) + { + LV_LOG_ERROR("NULL pointer given !"); + return; + } + + compassScreen->compassScreenOnStateChangeCb = compassScreenOnStateChangeCb; +} + +void compass_screen_register_azimuth_and_temperature_cb(CompassScreen_t * const compassScreen, CompassScreenAzimuthAndTemperatureCb_t compassScreenAzimuthAndTemperatureCb) +{ + if(!compassScreen) + { + LV_LOG_ERROR("NULL pointer given !"); + return; + } + + compassScreen->compassScreenAzimuthAndTemperatureCb = compassScreenAzimuthAndTemperatureCb; } void compass_screen_set_azimuth(CompassScreen_t * const compassScreen, uint16_t azimuth) @@ -317,6 +358,18 @@ void compass_screen_create(CompassScreen_t * const compassScreen) lv_obj_add_event_cb(compassScreen->display, &(gesture_event_cb), LV_EVENT_GESTURE, compassScreen); //We register the event callback to handle the cleanup lv_obj_add_event_cb(compassScreen->display, &(cleanup_event_cb), LV_EVENT_DELETE, compassScreen); + + //We create the refresh timer + if(compassScreen->refreshTimer) + { + LV_LOG_ERROR("refreshTimer should be NULL here !"); + lv_timer_del(compassScreen->refreshTimer); + compassScreen->refreshTimer = NULL; + } + + if(compassScreen->compassScreenOnStateChangeCb) compassScreen->compassScreenOnStateChangeCb(COMPASS_SCREEN_STATE_OPENED); + + compassScreen->refreshTimer = lv_timer_create(&(_compass_screen_refresh_timer_cb), 20, compassScreen); } void compass_screen_destroy(CompassScreen_t * const compassScreen) @@ -337,4 +390,7 @@ void compass_screen_destroy(CompassScreen_t * const compassScreen) compassScreen->northMarker = NULL; //compassScreen->compassGraduation.meter = NULL; //compassScreen->compassGraduation.scale = NULL; + compassScreen->refreshTimer = NULL; + + if(compassScreen->compassScreenOnStateChangeCb) compassScreen->compassScreenOnStateChangeCb(COMPASS_SCREEN_STATE_CLOSED); } diff --git a/src/W800_SDK_v1.00.10/app/gfx/compass_screen.h b/src/W800_SDK_v1.00.10/app/gfx/compass_screen.h index e03a730..cb76b04 100644 --- a/src/W800_SDK_v1.00.10/app/gfx/compass_screen.h +++ b/src/W800_SDK_v1.00.10/app/gfx/compass_screen.h @@ -22,6 +22,15 @@ typedef struct CompassCardinal lv_meter_scale_t *scale; } CompassGraduation_t;*/ +typedef enum CompassScreenState +{ + COMPASS_SCREEN_STATE_OPENED = 0, + COMPASS_SCREEN_STATE_CLOSED +} CompassScreenState_e; + +typedef void (*CompassScreenOnStateChangeCb_t)(CompassScreenState_e compassScreenState); +typedef void (*CompassScreenAzimuthAndTemperatureCb_t)(uint16_t *azimuth, bool *refreshAzimuth, float *temperature, bool *refreshTemperature); + /* Compass screen context object */ typedef struct CompassScreen { @@ -37,6 +46,11 @@ typedef struct CompassScreen CompassLabel_t compassAzimuth; CompassLabel_t compassTemperature; + + CompassScreenOnStateChangeCb_t compassScreenOnStateChangeCb; + CompassScreenAzimuthAndTemperatureCb_t compassScreenAzimuthAndTemperatureCb; + + lv_timer_t *refreshTimer; } CompassScreen_t; /** @@ -47,6 +61,26 @@ typedef struct CompassScreen */ void compass_screen_init(CompassScreen_t * const compassScreen); +/** + * @brief Registers a callback function which will be called every time the state of the application changes ie : is opened or closed. + * This callback should be used to initialize and deinitialize needed devices drivers like the magnetometer or the temperature sensor. + * @note The state of the application is passed as a parameter or the callback function. + * + * @param compassScreen a pointer to the compass screen object structure. + * @param compassScreenOnStateChangeCb the callback of type @ref CompassScreenOnStateChangeCb_t to register. + */ +void compass_screen_register_on_state_change_cb(CompassScreen_t * const compassScreen, CompassScreenOnStateChangeCb_t compassScreenOnStateChangeCb); + +/** + * @brief Registers a callback function which will be executed every time the compass refreshes. + * This callback should retrieve the azimuth and temperature and pass it through the provided pointers. + * @note If no new magnetometer or temperature data is available upon the function call, set the associated refresh parameter to false; + * + * @param compassScreen a pointer to the compass screen object structure. + * @param compassScreenOnStateChangeCb the callback of type CompassScreenAzimuthAndTemperatureCb_t to register. + */ +void compass_screen_register_azimuth_and_temperature_cb(CompassScreen_t * const compassScreen, CompassScreenAzimuthAndTemperatureCb_t compassScreenAzimuthAndTemperatureCb); + /** * @brief Sets the azimuth in degrees (relative to the north) to show on the compass UI. * diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.c b/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.c index 19ff8e8..473f51f 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.c +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.c @@ -28,6 +28,8 @@ static void gesture_event_cb(lv_event_t * e) break; case LV_DIR_RIGHT: LV_LOG_USER("GESTURE : RIGHT"); + // We delete the refresh timer + lv_timer_del(compassScreen->refreshTimer); // We create the menu screen and switch to it extern MenuScreen_t menuScreen; menu_screen_create(&menuScreen); @@ -44,8 +46,6 @@ static void gesture_event_cb(lv_event_t * e) } } -static lv_timer_t *timer; - static void cleanup_event_cb(lv_event_t * e) { CompassScreen_t *compassScreen = e->user_data; @@ -53,18 +53,20 @@ static void cleanup_event_cb(lv_event_t * e) LV_LOG_USER("cleanup"); } -//To delete -static void timer_anim_cb(lv_timer_t *timer) +static void _compass_screen_refresh_timer_cb(lv_timer_t *timer) { CompassScreen_t *compassScreen = timer->user_data; - static uint16_t azimuth = 0; - static float temp = -20; - compass_screen_set_azimuth(compassScreen, azimuth++); - compass_screen_set_temperature(compassScreen, temp+=0.09); - if(temp > 120) temp = -20; + if(compassScreen->compassScreenAzimuthAndTemperatureCb) + { + uint16_t azimuth = 0; + float temperature = 0.0f; - //lv_meter_set_scale_range(compassScreen->compassGraduation.meter, compassScreen->compassGraduation.scale, 0, 330, 330, -azimuth-90); + compassScreen->compassScreenAzimuthAndTemperatureCb(&azimuth, &temperature); + + compass_screen_set_azimuth(compassScreen, azimuth); + compass_screen_set_temperature(compassScreen, temperature); + } } static void create_cardinal(CompassCardinal_t *cardidanl, const char *cardinalText, lv_color_t textColor, lv_coord_t x, lv_coord_t y, lv_obj_t *parent) @@ -106,6 +108,28 @@ void compass_screen_init(CompassScreen_t * const compassScreen) strcpy(compassScreen->compassTemperature.text, "0.00°C"); } +void compass_screen_register_on_state_change_cb(CompassScreen_t * const compassScreen, CompassScreenOnStateChangeCb_t compassScreenOnStateChangeCb) +{ + if(!compassScreen) + { + LV_LOG_ERROR("NULL pointer given !"); + return; + } + + compassScreen->compassScreenOnStateChangeCb = compassScreenOnStateChangeCb; +} + +void compass_screen_register_azimuth_and_temperature_cb(CompassScreen_t * const compassScreen, CompassScreenAzimuthAndTemperatureCb_t compassScreenAzimuthAndTemperatureCb) +{ + if(!compassScreen) + { + LV_LOG_ERROR("NULL pointer given !"); + return; + } + + compassScreen->compassScreenAzimuthAndTemperatureCb = compassScreenAzimuthAndTemperatureCb; +} + void compass_screen_set_azimuth(CompassScreen_t * const compassScreen, uint16_t azimuth) { if(!compassScreen) @@ -165,7 +189,17 @@ void compass_screen_set_temperature(CompassScreen_t * const compassScreen, float //Update the temperature label sprintf(compassScreen->compassTemperature.text, "%.2f°C", temperature); lv_label_set_text_static(compassScreen->compassTemperature.label, compassScreen->compassTemperature.text); +} +bool compass_screen_is_in_use(CompassScreen_t *const compassScreen) +{ + if(!compassScreen) + { + LV_LOG_ERROR("NULL pointer given !"); + return false; + } + + return compassScreen->display != NULL; } void compass_screen_create(CompassScreen_t * const compassScreen) @@ -191,7 +225,7 @@ void compass_screen_create(CompassScreen_t * const compassScreen) compassScreen->display = lv_obj_create(NULL); lv_obj_set_style_bg_color(compassScreen->display, lv_color_white(), LV_PART_MAIN); - //Let's try to add some arcs + //Let's add some arcs lv_obj_t *arc = lv_arc_create(compassScreen->display); lv_arc_set_angles(arc, 0, 360); lv_obj_set_style_arc_width(arc, 2, LV_PART_INDICATOR); @@ -308,8 +342,17 @@ void compass_screen_create(CompassScreen_t * const compassScreen) //We register the event callback to handle the cleanup lv_obj_add_event_cb(compassScreen->display, &(cleanup_event_cb), LV_EVENT_DELETE, compassScreen); - //To delete - timer = lv_timer_create(&(timer_anim_cb), 2, compassScreen); + //We create the refresh timer + if(compassScreen->refreshTimer) + { + LV_LOG_ERROR("refreshTimer should be NULL here !"); + lv_timer_del(compassScreen->refreshTimer); + compassScreen->refreshTimer = NULL; + } + + if(compassScreen->compassScreenOnStateChangeCb) compassScreen->compassScreenOnStateChangeCb(COMPASS_SCREEN_OPENED); + + compassScreen->refreshTimer = lv_timer_create(&(_compass_screen_refresh_timer_cb), 20, compassScreen); } void compass_screen_destroy(CompassScreen_t * const compassScreen) @@ -330,6 +373,7 @@ void compass_screen_destroy(CompassScreen_t * const compassScreen) compassScreen->northMarker = NULL; compassScreen->compassGraduation.meter = NULL; compassScreen->compassGraduation.scale = NULL; + compassScreen->refreshTimer = NULL; - lv_timer_del(timer); + if(compassScreen->compassScreenOnStateChangeCb) compassScreen->compassScreenOnStateChangeCb(COMPASS_SCREEN_CLOSED); } diff --git a/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.h b/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.h index 244100e..b5af5e1 100644 --- a/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.h +++ b/src/lvgl_win_sim/lv_port_win_codeblocks/compass_screen.h @@ -22,6 +22,16 @@ typedef struct CompassGraduation lv_meter_scale_t *scale; } CompassGraduation_t; +typedef enum CompassScreenState +{ + COMPASS_SCREEN_OPENED = 0, + COMPASS_SCREEN_CLOSED +} CompassScreenState_e; + +typedef void (*CompassScreenOnStateChangeCb_t)(CompassScreenState_e compassScreenState); + +typedef void (*CompassScreenAzimuthAndTemperatureCb_t)(uint16_t *azimuth, float *temperature); + /* Compass screen context object */ typedef struct CompassScreen { @@ -37,21 +47,77 @@ typedef struct CompassScreen CompassLabel_t compassAzimuth; CompassLabel_t compassTemperature; + + CompassScreenOnStateChangeCb_t compassScreenOnStateChangeCb; + CompassScreenAzimuthAndTemperatureCb_t compassScreenAzimuthAndTemperatureCb; + + lv_timer_t *refreshTimer; } CompassScreen_t; -/* Initializes the compass screen context object */ +/** + * @brief Initializes the compass screen object structure. + * @note This function has to be called first before any others. + * + * @param compassScreen a pointer to the compass screen object structure to initialize. + */ void compass_screen_init(CompassScreen_t * const compassScreen); -/* Set the compassAzimuth in degrees to show */ +/** + * @brief Registers a callback function which will be called every time the state of the application changes ie : is opened or closed. + * This callback should be used to initialize and deinitialize needed devices drivers like the magnetometer or the temperature sensor. + * @note The state of the application is passed as a parameter or the callback function. + * + * @param compassScreen a pointer to the compass screen object structure. + * @param compassScreenOnStateChangeCb the callback of type CompassScreenOnStateChangeCb_t to register. + */ +void compass_screen_register_on_state_change_cb(CompassScreen_t * const compassScreen, CompassScreenOnStateChangeCb_t compassScreenOnStateChangeCb); + +/** + * @brief Registers a callback function which will be executed every time the compass refreshes. + * This callback should retrieve the azimuth and temperature and pass it through the provided pointers. + * + * @param compassScreen a pointer to the compass screen object structure. + * @param compassScreenOnStateChangeCb the callback of type CompassScreenAzimuthAndTemperatureCb_t to register. + */ +void compass_screen_register_azimuth_and_temperature_cb(CompassScreen_t * const compassScreen, CompassScreenAzimuthAndTemperatureCb_t compassScreenAzimuthAndTemperatureCb); + +/** + * @brief Sets the azimuth in degrees (relative to the north) to show on the compass UI. + * + * @param compassScreen a pointer to the compass screen object structure. + * @param azimuth the azimuth in degrees (0 to 359) relative to north to show. + */ void compass_screen_set_azimuth(CompassScreen_t * const compassScreen, uint16_t azimuth); -/* Set the compassTemperature in degrees celsius to show */ +/** + * @brief Sets the temperature in degrees celsius to show on the compass UI. + * + * @param compassScreen a pointer to the compass screen object structure. + * @param temperature the temperature to display on the compass screen in degrees celsius. + */ void compass_screen_set_temperature(CompassScreen_t * const compassScreen, float temperature); -/* Builds the compass screen graphically */ +/** + * @brief Returns true if the compass screen is currently being used and displayed. + * + * @param compassScreen a pointer to the compass screen object structure. + * @return true if the compass screen is being used . + * @return false if the compass screen is not being used/currently displayed. + */ +bool compass_screen_is_in_use(CompassScreen_t * const compassScreen); + +/** + * @brief Builds the compass screen graphically. + * + * @param compassScreen a pointer to the compass screen object structure. + */ void compass_screen_create(CompassScreen_t * const compassScreen); -/* Frees all resources used by the CompassScreen object */ +/** + * @brief Frees all resources used by the CompassScreen object, to be called when discarding the compass screen. + * + * @param compassScreen a pointer to the compass screen object structure. + */ void compass_screen_destroy(CompassScreen_t * const compassScreen); #endif // COMPASS_SCREEN_H