diff --git a/lv_misc/anim.c b/lv_misc/anim.c index ab415d68c..185178ae6 100644 --- a/lv_misc/anim.c +++ b/lv_misc/anim.c @@ -6,50 +6,34 @@ /********************* * INCLUDES *********************/ -#include -#include -#include "lvgl/lvgl.h" +#include +#include "anim.h" +#include "misc/os/ptask.h" +#include "hal/systick/systick.h" + /********************* * DEFINES *********************/ +#define ANIM_PATH_LENGTH 129 /*Elements in a path array*/ +#define ANIM_PATH_START 64 /*In path array a value which corresponds to the start position*/ +#define ANIM_PATH_END 192 /* ... to the end position. Not required, just for clearance.*/ +#define ANIM_PATH_NORM_SHIFT 7 /*ANIM_PATH_START - ANIM_PATH_END. Must be 2^N. The exponent goes here. */ /********************** * TYPEDEFS **********************/ -typedef uint8_t anim_path_t; - -typedef struct -{ - -}anim_t; - -typedef enum -{ - ANIM_NONE = 0, - ANIM_SHOW, - ANIM_FLOAT_TOP, - ANIM_FLOAT_LEFT, - ANIM_FLOAT_BOTTOM, - ANIM_FLOAT_RIGHT, - ANIM_SLIDE_TOP, - ANIM_SLIDE_LEFT, - ANIM_SLIDE_BOTTOM, - ANIM_SLIDE_RIGHT, - ANIM_FADE, - ANIM_FADER, - ANIM_SIZE, - ANIM_PINGPONG_H, - ANIM_PINGPONG_V, -}anim_builtin_t; /********************** * STATIC PROTOTYPES **********************/ +static void anim_task (void); /********************** * STATIC VARIABLES **********************/ +static ll_dsc_t anim_ll; +static uint32_t last_task_run; /********************** * MACROS @@ -59,34 +43,81 @@ typedef enum * GLOBAL FUNCTIONS **********************/ -void anim_start(lv_obj_t * obj_dp, anim_builtin_t anim, uint32_t t, uint32_t delay) +/** + * Init. the animation module + */ +void anim_init(void) { - + ll_init(&anim_ll, sizeof(anim_t)); + last_task_run = systick_get(); + ptask_create(anim_task, LV_REFR_PERIOD, PTASK_PRIO_MID); } -anim_t * anim_create(void * p, void * fp, int32_t v1, int32_t v2, anim_path_t * path_p) +/** + * Create an animation + * @param anim_p an initialized 'anim_t' variable. Not required after call. + */ +void anim_create(anim_t * anim_p) { - return NULL; + anim_t * new_anim_dp = ll_ins_head(&anim_ll); + dm_assert(new_anim_dp); + + memcpy(new_anim_dp, anim_p, sizeof(anim_t)); + + new_anim_dp->fp(new_anim_dp->p, new_anim_dp->start); } -void ani_set_cb(anim_t * anim_dp, void (*cb)(void *, void *)) -{ - -} - -void anim_start_t(anim_t anim_dp, uint32_t time, uint32_t delay) -{ - -} - - -void anim_start_v(anim_t anim_dp, uint32_t v, uint32_t delay) -{ - -} - - /********************** * STATIC FUNCTIONS **********************/ + +/** + * Periodically handle animations. + */ +static void anim_task (void) +{ + uint32_t elaps; + elaps = systick_elaps(last_task_run); + + anim_t * a; + anim_t * a_next; + a = ll_get_head(&anim_ll); + while(a != NULL) { + /*'a' might be deleted, so get the next object while 'a' is valid*/ + a_next = ll_get_next(&anim_ll, a); + + a->act_time += elaps; + if(a->act_time >= 0) { + if(a->act_time > a->time) a->act_time = a->time; + + /* Get the index of the path array based on the elapsed time*/ + uint8_t path_i; + path_i = a->act_time * (ANIM_PATH_LENGTH - 1) / a->time; + + /* Get the new value which will be proportional to the current element of 'path_p' + * and the 'start' and 'end' values*/ + int32_t new_val; + new_val = (int32_t)(a->path_p[path_i] - ANIM_PATH_START) * (a->end - a->start); + new_val = new_val >> ANIM_PATH_NORM_SHIFT; + new_val += a->start; + + a->fp(a->p, new_val); /*Apply the calculated value*/ + + /*Delete the animation if it is ready*/ + if(a->act_time >= a->time) { + void (*cb) (void *) = a->end_cb; + void * p = a->p; + ll_rem(&anim_ll, a); + dm_free(a); + + /*Call the callback function at the end*/ + if(cb != NULL) cb(p); + } + } + + a = a_next; + } + + last_task_run = systick_get(); +} diff --git a/lv_misc/anim.h b/lv_misc/anim.h index e69de29bb..4d3b29d06 100644 --- a/lv_misc/anim.h +++ b/lv_misc/anim.h @@ -0,0 +1,45 @@ +/** + * @file anim.h + * + */ + +#ifndef ANIM_H +#define ANIM_H + +/********************* + * INCLUDES + *********************/ +#include "lvgl/lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef uint8_t anim_path_t; + +typedef struct +{ + void * p; /*Variable to animate*/ + void (*fp) (void *, int32_t); /*Animator function*/ + void (*end_cb) (void *); /*Call it when the animation is ready*/ + anim_path_t * path_p; /*An array with the steps of animations*/ + int32_t start; /*Start value*/ + int32_t end; /*End value*/ + int16_t time; /*Animation time in ms*/ + int16_t act_time; /*Current time in animation. Set to negative to make delay.*/ +}anim_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void anim_init(void); +void anim_create(anim_t * anim_p); + +/********************** + * MACROS + **********************/ + +#endif diff --git a/lv_obj/lv_obj.c b/lv_obj/lv_obj.c index c4eb1c2ab..aa369cac2 100644 --- a/lv_obj/lv_obj.c +++ b/lv_obj/lv_obj.c @@ -9,6 +9,7 @@ #include "lv_obj.h" #include "../lv_draw/lv_draw_rbasic.h" #include "../lv_draw/lv_draw_vbasic.h" +#include "../lv_misc/anim.h" #include "lv_dispi.h" #include "lv_refr.h" #include "misc/math/math_base.h" @@ -39,6 +40,12 @@ lv_objs_t lv_objs_def = {.color = COLOR_MAKE(0xa0, 0xc0, 0xe0), .transp = 0}; lv_objs_t lv_objs_scr = {.color = LV_OBJ_DEF_SCR_COLOR, .transp = 0}; lv_objs_t lv_objs_transp = {.transp = 1}; +static anim_path_t anim_path_lin[] = + {64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192}; + /********************** * MACROS **********************/ @@ -60,6 +67,9 @@ void lv_init(void) /*Init. the screen refresh system*/ lv_refr_init(); + /*Init. the animations*/ + anim_init(); + /*Create the default screen*/ ll_init(&scr_ll, sizeof(lv_obj_t)); def_scr_dp = lv_obj_create(NULL, NULL); @@ -952,6 +962,88 @@ void lv_obj_set_free_p(lv_obj_t* obj_dp, void * free_p) obj_dp->free_p = free_p; } #endif + +/** + * Animate an object + * @param obj_dp pointer to an object to animate + * @param type type of animation from 'lv_anim_builtin_t'. 'OR' it with ANIM_IN or ANIM_OUT + * @param time time of animation in milliseconds + * @param delay delay before the animation in milliseconds + * @param cb a function to call when the animation is ready + */ +void lv_obj_anim(lv_obj_t * obj_dp, lv_anim_builtin_t type, uint16_t time, uint16_t delay, void (*cb) (lv_obj_t *)) +{ + lv_obj_t * par_dp = lv_obj_get_parent(obj_dp); + + /*Get the direction*/ + bool out = (type & ANIM_DIR_MASK) == ANIM_IN ? false : true; + type = type & (~ANIM_DIR_MASK); + + if(type == ANIM_NONE) return; + + anim_t a; + a.p = obj_dp; + a.time = time; + a.act_time = (int32_t)-delay; + a.end_cb = (void(*)(void*))cb; + + /*Init to ANIM_IN*/ + switch(type) { + case ANIM_FLOAT_LEFT: + a.fp = (void(*)(void *, int32_t))lv_obj_set_x; + a.start = -lv_obj_get_width(obj_dp); + a.end = lv_obj_get_x(obj_dp); + a.path_p = anim_path_lin; + break; + case ANIM_FLOAT_RIGHT: + a.fp = (void(*)(void *, int32_t))lv_obj_set_x; + a.start = lv_obj_get_width(par_dp); + a.end = lv_obj_get_x(obj_dp); + a.path_p = anim_path_lin; + break; + case ANIM_FLOAT_TOP: + a.fp = (void(*)(void * , int32_t))lv_obj_set_y; + a.start = -lv_obj_get_height(obj_dp); + a.end = lv_obj_get_y(obj_dp); + a.path_p = anim_path_lin; + break; + case ANIM_FLOAT_BOTTOM: + a.fp = (void(*)(void * , int32_t))lv_obj_set_y; + a.start = lv_obj_get_height(par_dp); + a.end = lv_obj_get_y(obj_dp); + a.path_p = anim_path_lin; + break; + case ANIM_FADE: + a.fp = (void(*)(void * , int32_t))lv_obj_set_opar; + a.start = OPA_TRANSP; + a.end = OPA_COVER; + a.path_p = anim_path_lin; + break; + case ANIM_GROW_H: + a.fp = (void(*)(void * , int32_t))lv_obj_set_width; + a.start = 0; + a.end = lv_obj_get_width(obj_dp); + a.path_p = anim_path_lin; + break; + case ANIM_GROW_V: + a.fp = (void(*)(void * , int32_t))lv_obj_set_height; + a.start = 0; + a.end = lv_obj_get_height(obj_dp); + a.path_p = anim_path_lin; + break; + default: + break; + } + + /*Swap start and end in case of ANIM OUT*/ + if(out != false) { + int32_t tmp = a.start; + a.start = a.end; + a.end = tmp; + } + + anim_create(&a); +} /*======================= * Getter functions *======================*/ diff --git a/lv_obj/lv_obj.h b/lv_obj/lv_obj.h index 9a00ba866..613fa1159 100644 --- a/lv_obj/lv_obj.h +++ b/lv_obj/lv_obj.h @@ -42,6 +42,10 @@ #define LV_OBJ_DEF_WIDTH (80 * LV_DOWNSCALE) #define LV_OBJ_DEF_HEIGHT (60 * LV_DOWNSCALE) +#define ANIM_IN 0x00 /*Animation to show an object. 'OR' it with lv_anim_builtin_t*/ +#define ANIM_OUT 0x80 /*Animation to hide an object. 'OR' it with lv_anim_builtin_t*/ +#define ANIM_DIR_MASK 0x80 /*ANIM_IN/ANIM_OUT mask*/ + /********************** * TYPEDEFS **********************/ @@ -144,6 +148,18 @@ typedef enum LV_OBJS_TRANSP, }lv_objs_builtin_t; +typedef enum +{ + ANIM_NONE = 0, + ANIM_FADE, + ANIM_FLOAT_TOP, + ANIM_FLOAT_LEFT, + ANIM_FLOAT_BOTTOM, + ANIM_FLOAT_RIGHT, + ANIM_GROW_H, + ANIM_GROW_V, +}lv_anim_builtin_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -195,7 +211,7 @@ void lv_obj_set_style(lv_obj_t* obj_dp, void * style_p); void * lv_obj_iso_style(lv_obj_t * obj_dp, uint32_t style_size); void lv_obj_set_free_num(lv_obj_t* obj_dp, uint8_t free_num); void lv_obj_set_free_p(lv_obj_t* obj_dp, void * free_p); -void lv_obj_merge_style(lv_obj_t* obj_dp); +void lv_obj_anim(lv_obj_t * obj_dp, lv_anim_builtin_t anim, uint16_t time, uint16_t delay, void (*cb) (lv_obj_t *)); /*GETTER FUNCTIONS*/ /*Screen get*/ diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index d47bf5974..bdaf43c38 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -25,7 +25,9 @@ /********************** * STATIC PROTOTYPES **********************/ +#if 0 static bool lv_list_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode); +#endif /********************** * STATIC VARIABLES @@ -300,6 +302,7 @@ lv_list_fit_t lv_list_get_fit(lv_obj_t * obj_dp) * STATIC FUNCTIONS **********************/ +#if 0 /*A new design function is not necessary*/ /** * Handle the drawing related tasks of the lists * @param obj_dp pointer to an object @@ -316,11 +319,11 @@ static bool lv_list_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mo return false; } - /*Draw the object*/ return true; } +#endif #endif