diff --git a/src/lv_misc/lv_anim.c b/src/lv_misc/lv_anim.c index 41357dfe5..4b01b8051 100644 --- a/src/lv_misc/lv_anim.c +++ b/src/lv_misc/lv_anim.c @@ -1,5 +1,5 @@ /** - * @file lv_anim.c + * @file anim.c * */ @@ -33,14 +33,13 @@ **********************/ static void anim_task(lv_task_t * param); static void anim_mark_list_change(void); -static void anim_ready_handler(lv_anim_t * a); +static bool anim_ready_handler(lv_anim_t * a); /********************** * STATIC VARIABLES **********************/ static uint32_t last_task_run; static bool anim_list_changed; -static bool anim_run_round; static lv_task_t * _lv_anim_task; const lv_anim_path_t lv_anim_path_def = {.cb = lv_anim_path_linear}; @@ -58,6 +57,7 @@ const lv_anim_path_t lv_anim_path_def = {.cb = lv_anim_path_linear}; void _lv_anim_core_init(void) { _lv_ll_init(&LV_GC_ROOT(_lv_anim_ll), sizeof(lv_anim_t)); + last_task_run = lv_tick_get(); _lv_anim_task = lv_task_create(anim_task, LV_DISP_DEF_REFR_PERIOD, LV_ANIM_TASK_PRIO, NULL); anim_mark_list_change(); /*Turn off the animation task*/ anim_list_changed = false; /*The list has not actually changed*/ @@ -93,7 +93,7 @@ void lv_anim_start(lv_anim_t * a) /*If the list is empty the anim task was suspended and it's last run measure is invalid*/ if(_lv_ll_is_empty(&LV_GC_ROOT(_lv_anim_ll))) { - last_task_run = lv_tick_get(); + last_task_run = lv_tick_get() - 1; } /*Add the new animation to the animation linked list*/ @@ -103,7 +103,6 @@ void lv_anim_start(lv_anim_t * a) /*Initialize the animation descriptor*/ a->time_orig = a->time; - a->run_round = anim_run_round; _lv_memcpy(new_anim, a, sizeof(lv_anim_t)); /*Set the start value*/ @@ -188,10 +187,12 @@ uint16_t lv_anim_count_running(void) * @param end end value of the animation * @return the required time [ms] for the animation with the given parameters */ -uint32_t lv_anim_speed_to_time(uint32_t speed, lv_anim_value_t start, lv_anim_value_t end) +uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end) { - uint32_t d = LV_MATH_ABS(start - end); - uint32_t time = (d * 1000) / speed; + int32_t d = LV_MATH_ABS((int32_t)start - end); + uint32_t time = (int32_t)((int32_t)(d * 1000) / speed); + + if(time > UINT16_MAX) time = UINT16_MAX; if(time == 0) { time++; @@ -221,16 +222,22 @@ lv_anim_value_t lv_anim_path_linear(const lv_anim_path_t * path, const lv_anim_t LV_UNUSED(path); /*Calculate the current step*/ - int32_t step = _lv_map(a->act_time, 0, a->time, 0, LV_ANIM_RESOLUTION); + uint32_t step; + if(a->time == a->act_time) { + step = LV_ANIM_RESOLUTION; /*Use the last value if the time fully elapsed*/ + } + else { + step = ((int32_t)a->act_time * LV_ANIM_RESOLUTION) / a->time; + } /* Get the new value which will be proportional to `step` * and the `start` and `end` values*/ int32_t new_value; - new_value = step * (a->end - a->start); + new_value = (int32_t)step * (a->end - a->start); new_value = new_value >> LV_ANIM_RES_SHIFT; new_value += a->start; - return new_value; + return (lv_anim_value_t)new_value; } /** @@ -243,16 +250,20 @@ lv_anim_value_t lv_anim_path_ease_in(const lv_anim_path_t * path, const lv_anim_ LV_UNUSED(path); /*Calculate the current step*/ + uint32_t t; + if(a->time == a->act_time) + t = 1024; + else + t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t step = _lv_bezier3(t, 0, 1, 1, 1024); int32_t new_value; - new_value = step * (a->end - a->start); + new_value = (int32_t)step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return new_value; + return (lv_anim_value_t)new_value; } /** @@ -266,15 +277,20 @@ lv_anim_value_t lv_anim_path_ease_out(const lv_anim_path_t * path, const lv_anim /*Calculate the current step*/ - uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); + uint32_t t; + if(a->time == a->act_time) + t = 1024; + else + t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; + int32_t step = _lv_bezier3(t, 0, 1023, 1023, 1024); int32_t new_value; - new_value = step * (a->end - a->start); + new_value = (int32_t)step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return new_value; + return (lv_anim_value_t)new_value; } /** @@ -288,15 +304,20 @@ lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_path_t * path, const lv_a /*Calculate the current step*/ - uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); + uint32_t t; + if(a->time == a->act_time) + t = 1024; + else + t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; + int32_t step = _lv_bezier3(t, 0, 100, 924, 1024); int32_t new_value; - new_value = step * (a->end - a->start); + new_value = (int32_t)step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return new_value; + return (lv_anim_value_t)new_value; } /** @@ -310,15 +331,20 @@ lv_anim_value_t lv_anim_path_overshoot(const lv_anim_path_t * path, const lv_ani /*Calculate the current step*/ - uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); + uint32_t t; + if(a->time == a->act_time) + t = 1024; + else + t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; + int32_t step = _lv_bezier3(t, 0, 1000, 1300, 1024); int32_t new_value; - new_value = step * (a->end - a->start); + new_value = (int32_t)step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return new_value; + return (lv_anim_value_t)new_value; } /** @@ -331,8 +357,12 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_path_t * path, const lv_anim_t LV_UNUSED(path); /*Calculate the current step*/ + int32_t t; + if(a->time == a->act_time) + t = 1024; + else + t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t diff = (a->end - a->start); /*3 bounces has 5 parts: 3 down and 2 up. One part is t / 5 long*/ @@ -361,21 +391,24 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_path_t * path, const lv_anim_t t = 1024 - t; diff = diff / 40; } - else { + else if(t >= 921 && t <= 1024) { /*Fall back*/ t -= 921; t = t * 10; /*to [0..1024] range*/ diff = diff / 40; } + if(t > 1024) t = 1024; + if(t < 0) t = 0; + int32_t step = _lv_bezier3(t, 1024, 800, 500, 0); int32_t new_value; - new_value = step * diff; + new_value = (int32_t)step * diff; new_value = new_value >> 10; new_value = a->end - new_value; - return new_value; + return (lv_anim_value_t)new_value; } /** @@ -406,12 +439,14 @@ static void anim_task(lv_task_t * param) { (void)param; + lv_anim_t * a; + _LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) { + a->has_run = 0; + } + uint32_t elaps = lv_tick_elaps(last_task_run); - /*Flip the run round*/ - anim_run_round = anim_run_round ? false : true; - - lv_anim_t * a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); + a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); while(a != NULL) { /*It can be set by `lv_anim_del()` typically in `end_cb`. If set then an animation delete @@ -420,8 +455,8 @@ static void anim_task(lv_task_t * param) */ anim_list_changed = false; - if(a->run_round != anim_run_round) { - a->run_round = anim_run_round; /*The list readying might be reset so need to know which anim has run already*/ + if(!a->has_run) { + a->has_run = 1; /*The list readying might be reset so need to know which anim has run already*/ /*The animation will run now for the first time. Call `start_cb`*/ int32_t new_act_time = a->act_time + elaps; @@ -464,8 +499,9 @@ static void anim_task(lv_task_t * param) * Called when an animation is ready to do the necessary thinks * e.g. repeat, play back, delete etc. * @param a pointer to an animation descriptor - */ -static void anim_ready_handler(lv_anim_t * a) + * @return true: animation delete occurred and the `LV_GC_ROOT(_lv_anim_ll)` has changed + * */ +static bool anim_ready_handler(lv_anim_t * a) { /*In the end of a forward anim decrement repeat cnt.*/ if(a->playback_now == 0 && a->repeat_cnt > 0 && a->repeat_cnt != LV_ANIM_REPEAT_INFINITE) { @@ -508,6 +544,8 @@ static void anim_ready_handler(lv_anim_t * a) a->time = a->playback_now == 0 ? a->time_orig : a->playback_time; } } + + return anim_list_changed; } static void anim_mark_list_change(void) { diff --git a/src/lv_misc/lv_anim.h b/src/lv_misc/lv_anim.h index 8f0161329..54baf5969 100644 --- a/src/lv_misc/lv_anim.h +++ b/src/lv_misc/lv_anim.h @@ -1,10 +1,10 @@ /** - * @file lv_anim.h + * @file anim.h * */ -#ifndef LV_ANIM_H -#define LV_ANIM_H +#ifndef ANIM_H +#define ANIM_H #ifdef __cplusplus extern "C" { @@ -37,7 +37,7 @@ enum { typedef uint8_t lv_anim_enable_t; /** Type of the animated value*/ -typedef int32_t lv_anim_value_t; +typedef lv_coord_t lv_anim_value_t; #if LV_USE_ANIMATION @@ -74,28 +74,28 @@ typedef void (*lv_anim_start_cb_t)(struct _lv_anim_t *); /** Describes an animation*/ typedef struct _lv_anim_t { void * var; /**var = var; + a->var = var; } /** @@ -146,7 +146,7 @@ static inline void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb */ static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration) { - a->time = duration; + a->time = duration; } /** @@ -169,7 +169,7 @@ static inline void lv_anim_set_values(lv_anim_t * a, lv_anim_value_t start, lv_a { a->start = start; a->current = start; - a->end = end; + a->end = end; } /** @@ -190,8 +190,8 @@ static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec /** * Set the path (curve) of the animation. * @param a pointer to an initialized `lv_anim_t` variable - * @param path a function the get the current value of the animation. - * The built in functions starts with `lv_anim_path_...` + * @param path_cb a function the get the current value of the animation. + * The built in functions starts with `lv_anim_path_...` */ static inline void lv_anim_set_path(lv_anim_t * a, const lv_anim_path_t * path) { @@ -223,7 +223,7 @@ static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_ * @param a pointer to an initialized `lv_anim_t` variable * @param time the duration of the playback animation in in milliseconds. 0: disable playback */ -static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) +static inline void lv_anim_set_playback_time(lv_anim_t * a, uint16_t time) { a->playback_time = time; } @@ -233,7 +233,7 @@ static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) * @param a pointer to an initialized `lv_anim_t` variable * @param delay delay in milliseconds before starting the playback animation. */ -static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) +static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint16_t delay) { a->playback_delay = delay; } @@ -245,7 +245,7 @@ static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) */ static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) { - a->repeat_cnt = cnt; + a->repeat_cnt = cnt; } /** @@ -253,7 +253,7 @@ static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) * @param a pointer to an initialized `lv_anim_t` variable * @param delay delay in milliseconds before repeating the animation. */ -static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint32_t delay) +static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint16_t delay) { a->repeat_delay = delay; } @@ -298,7 +298,7 @@ static inline void lv_anim_path_set_user_data(lv_anim_path_t * path, void * user * @param a pointer to an initialized `lv_anim_t` variable * @return delay before the animation in milliseconds */ -static inline uint32_t lv_anim_get_delay(lv_anim_t * a) +static inline int32_t lv_anim_get_delay(lv_anim_t * a) { return -a->act_time; } @@ -350,7 +350,7 @@ uint16_t lv_anim_count_running(void); * @param end end value of the animation * @return the required time [ms] for the animation with the given parameters */ -uint32_t lv_anim_speed_to_time(uint32_t speed, lv_anim_value_t start, lv_anim_value_t end); +uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end); /** * Manually refresh the state of the animations.