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

This commit is contained in:
anschrammh 2023-10-19 08:10:32 +02:00
parent 2fc99479c5
commit af71c44af4
4 changed files with 220 additions and 20 deletions

View File

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

View File

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

View File

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

View File

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