diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index d4239de5b..6fbb450c5 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -319,6 +319,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) #endif /*Set attributes*/ + new_obj->adv_hittest = 0; new_obj->click = 1; new_obj->drag = 0; new_obj->drag_dir = LV_DRAG_DIR_BOTH; @@ -368,6 +369,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->event_cb = copy->event_cb; /*Copy attributes*/ + new_obj->adv_hittest = copy->adv_hittest; new_obj->click = copy->click; new_obj->drag = copy->drag; new_obj->drag_dir = copy->drag_dir; diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index 54c0658ba..77fd95f13 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -135,6 +135,7 @@ void lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p) lv_area_copy(&disp->inv_areas[disp->inv_p], &scr_area); } disp->inv_p++; + lv_task_set_prio(disp->refr_task, LV_REFR_TASK_PRIO); } } @@ -168,6 +169,11 @@ void lv_disp_refr_task(lv_task_t * task) uint32_t start = lv_tick_get(); + /* Ensure the task does not run again automatically. + * This is done before refreshing in case refreshing invalidates something else. + */ + lv_task_set_prio(task, LV_TASK_PRIO_OFF); + disp_refr = task->user_data; lv_refr_join_area(); diff --git a/src/lv_core/lv_refr.h b/src/lv_core/lv_refr.h index 8c0ed03ed..35f2791c8 100644 --- a/src/lv_core/lv_refr.h +++ b/src/lv_core/lv_refr.h @@ -20,6 +20,8 @@ extern "C" { * DEFINES *********************/ +#define LV_REFR_TASK_PRIO LV_TASK_PRIO_MID + /********************** * TYPEDEFS **********************/ diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index 11a3bbcb2..9c1b30f32 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -133,7 +133,11 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) lv_disp_t * disp_def_tmp = disp_def; disp_def = disp; /*Temporarily change the default screen to create the default screens on the new display*/ - + /*Create a refresh task*/ + disp->refr_task = lv_task_create(lv_disp_refr_task, LV_DISP_DEF_REFR_PERIOD, LV_REFR_TASK_PRIO, disp); + LV_ASSERT_MEM(disp->refr_task); + if(disp->refr_task == NULL) return NULL; + disp->inv_p = 0; disp->act_scr = lv_obj_create(NULL, NULL); /*Create a default screen on the display*/ @@ -146,11 +150,6 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) disp_def = disp_def_tmp; /*Revert the default display*/ - /*Create a refresh task*/ - disp->refr_task = lv_task_create(lv_disp_refr_task, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, disp); - LV_ASSERT_MEM(disp->refr_task); - if(disp->refr_task == NULL) return NULL; - lv_task_ready(disp->refr_task); /*Be sure the screen will be refreshed immediately on start up*/ return disp; diff --git a/src/lv_misc/lv_anim.c b/src/lv_misc/lv_anim.c index 197959262..c5cd53946 100644 --- a/src/lv_misc/lv_anim.c +++ b/src/lv_misc/lv_anim.c @@ -26,6 +26,7 @@ *********************/ #define LV_ANIM_RESOLUTION 1024 #define LV_ANIM_RES_SHIFT 10 +#define LV_ANIM_TASK_PRIO LV_TASK_PRIO_MID /********************** * TYPEDEFS @@ -35,6 +36,7 @@ * STATIC PROTOTYPES **********************/ static void anim_task(lv_task_t * param); +static void anim_mark_list_change(void); static bool anim_ready_handler(lv_anim_t * a); /********************** @@ -42,6 +44,7 @@ static bool anim_ready_handler(lv_anim_t * a); **********************/ static uint32_t last_task_run; static bool anim_list_changed; +static lv_task_t * _lv_anim_task; /********************** * MACROS @@ -58,7 +61,9 @@ 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_task_create(anim_task, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, NULL); + _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 actaully changed*/ } /** @@ -102,7 +107,7 @@ void lv_anim_create(lv_anim_t * a) /* Creating an animation changed the linked list. * It's important if it happens in a ready callback. (see `anim_task`)*/ - anim_list_changed = true; + anim_mark_list_change(); LV_LOG_TRACE("animation created") } @@ -127,7 +132,7 @@ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) if(a->var == var && (a->exec_cb == exec_cb || exec_cb == NULL)) { lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); lv_mem_free(a); - anim_list_changed = true; /*Read by `anim_task`. It need to know if a delete occurred in + anim_mark_list_change(); /*Read by `anim_task`. It need to know if a delete occurred in the linked list*/ del = true; } @@ -457,7 +462,8 @@ static bool anim_ready_handler(lv_anim_t * a) memcpy(&a_tmp, a, sizeof(lv_anim_t)); lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); lv_mem_free(a); - anim_list_changed = true; + /*Flag that the list has changed */ + anim_mark_list_change(); /* Call the callback function at the end*/ if(a_tmp.ready_cb != NULL) a_tmp.ready_cb(&a_tmp); @@ -482,4 +488,12 @@ static bool anim_ready_handler(lv_anim_t * a) return anim_list_changed; } +static void anim_mark_list_change(void) +{ + anim_list_changed = true; + if(lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)) == NULL) + lv_task_set_prio(_lv_anim_task, LV_TASK_PRIO_OFF); + else + lv_task_set_prio(_lv_anim_task, LV_ANIM_TASK_PRIO); +} #endif diff --git a/src/lv_misc/lv_color.h b/src/lv_misc/lv_color.h index 0dce299f8..a480d9bc5 100644 --- a/src/lv_misc/lv_color.h +++ b/src/lv_misc/lv_color.h @@ -528,14 +528,14 @@ static inline uint8_t lv_color_brightness(lv_color_t color) /* The most simple macro to create a color from R,G and B values */ #if LV_COLOR_DEPTH == 1 -#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){.full = ((b8 >> 7) | (g8 >> 7) | (r8 >> 7))}) +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){.full = (uint8_t)((b8 >> 7) | (g8 >> 7) | (r8 >> 7))}) #elif LV_COLOR_DEPTH == 8 -#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(b8 >> 6) & 0x3U, (g8 >> 5) & 0x7U, (r8 >> 5) & 0x7U}}) +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(uint8_t)((b8 >> 6) & 0x3U), (uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 5) & 0x7U)}}) #elif LV_COLOR_DEPTH == 16 #if LV_COLOR_16_SWAP == 0 -#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(b8 >> 3) & 0x1FU, (g8 >> 2) & 0x3FU, (r8 >> 3) & 0x1FU}}) +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(uint16_t)((b8 >> 3) & 0x1FU), (uint16_t)((g8 >> 2) & 0x3FU), (uint16_t)((r8 >> 3) & 0x1FU)}}) #else -#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(g8 >> 5) & 0x7U, (r8 >> 3) & 0x1FU, (b8 >> 3) & 0x1FU, (g8 >> 2) & 0x7U}}) +#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(uint16_t)((g8 >> 5) & 0x7U), (uint16_t)((r8 >> 3) & 0x1FU), (uint16_t)((b8 >> 3) & 0x1FU), (uint16_t)((g8 >> 2) & 0x7U)}}) #endif #elif LV_COLOR_DEPTH == 32 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/ diff --git a/src/lv_misc/lv_task.c b/src/lv_misc/lv_task.c index 8a7bffca8..eb10e1813 100644 --- a/src/lv_misc/lv_task.c +++ b/src/lv_misc/lv_task.c @@ -32,6 +32,7 @@ * STATIC PROTOTYPES **********************/ static bool lv_task_exec(lv_task_t * task); +static uint32_t lv_task_time_remaining(lv_task_t * task); /********************** * STATIC VARIABLES @@ -39,6 +40,7 @@ static bool lv_task_exec(lv_task_t * task); static bool lv_task_run = false; static uint8_t idle_last = 0; static bool task_deleted; +static bool task_list_changed; static bool task_created; /********************** @@ -56,14 +58,16 @@ void lv_task_core_init(void) { lv_ll_init(&LV_GC_ROOT(_lv_task_ll), sizeof(lv_task_t)); + task_list_changed = false; /*Initially enable the lv_task handling*/ lv_task_enable(true); } /** * Call it periodically to handle lv_tasks. + * @return the time after which it must be called again */ -LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void) +LV_ATTRIBUTE_TASK_HANDLER uint32_t lv_task_handler(void) { @@ -71,16 +75,17 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void) /*Avoid concurrent running of the task handler*/ static bool already_running = false; - if(already_running) return; + if(already_running) return 1; already_running = true; static uint32_t idle_period_start = 0; static uint32_t handler_start = 0; static uint32_t busy_time = 0; + static uint32_t time_till_next; if(lv_task_run == false) { already_running = false; /*Release mutex*/ - return; + return 1; } handler_start = lv_tick_get(); @@ -149,6 +154,13 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void) break; } + if(task_list_changed) { + task_interrupter = NULL; + end_flag = false; + task_list_changed = false; + break; + } + LV_GC_ROOT(_lv_task_act) = next; /*Load the next task*/ } } while(!end_flag); @@ -162,10 +174,23 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void) busy_time = 0; idle_period_start = lv_tick_get(); } - + + time_till_next = LV_NO_TASK_READY; + next = lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll)); + while(next) { + if(next->prio != LV_TASK_PRIO_OFF) { + uint32_t delay = lv_task_time_remaining(next); + if(delay < time_till_next) + time_till_next = delay; + } + + next = lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), next); /*Find the next task*/ + } + already_running = false; /*Release the mutex*/ LV_LOG_TRACE("lv_task_handler ready"); + return time_till_next; } /** * Create an "empty" task. It needs to initialzed with at least @@ -205,6 +230,7 @@ lv_task_t * lv_task_create_basic(void) if(new_task == NULL) return NULL; } } + task_list_changed = true; new_task->period = DEF_PERIOD; new_task->task_cb = NULL; @@ -261,6 +287,7 @@ void lv_task_set_cb(lv_task_t * task, lv_task_cb_t task_cb) void lv_task_del(lv_task_t * task) { lv_ll_remove(&LV_GC_ROOT(_lv_task_ll), task); + task_list_changed = true; lv_mem_free(task); @@ -290,6 +317,7 @@ void lv_task_set_prio(lv_task_t * task, lv_task_prio_t prio) if(i == NULL) { lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, NULL); } + task_list_changed = true; task->prio = prio; } @@ -363,9 +391,7 @@ static bool lv_task_exec(lv_task_t * task) { bool exec = false; - /*Execute if at least 'period' time elapsed*/ - uint32_t elp = lv_tick_elaps(task->last_run); - if(elp >= task->period) { + if(lv_task_time_remaining(task) == 0) { task->last_run = lv_tick_get(); task_deleted = false; task_created = false; @@ -382,3 +408,17 @@ static bool lv_task_exec(lv_task_t * task) return exec; } + +/** + * Find out how much time remains before a task must be run. + * @param task pointer to lv_task + * @return the time remaining, or 0 if it needs to be run again + */ +static uint32_t lv_task_time_remaining(lv_task_t * task) +{ + /*Check if at least 'period' time elapsed*/ + uint32_t elp = lv_tick_elaps(task->last_run); + if(elp >= task->period) + return 0; + return task->period - elp; +} diff --git a/src/lv_misc/lv_task.h b/src/lv_misc/lv_task.h index a48b9c29c..a7acafdf7 100644 --- a/src/lv_misc/lv_task.h +++ b/src/lv_misc/lv_task.h @@ -27,6 +27,8 @@ extern "C" { #ifndef LV_ATTRIBUTE_TASK_HANDLER #define LV_ATTRIBUTE_TASK_HANDLER #endif + +#define LV_NO_TASK_READY 0xFFFFFFFF /********************** * TYPEDEFS **********************/ @@ -80,8 +82,9 @@ void lv_task_core_init(void); /** * Call it periodically to handle lv_tasks. + * @return time till it needs to be run next (in ms) */ -LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void); +LV_ATTRIBUTE_TASK_HANDLER uint32_t lv_task_handler(void); //! @endcond diff --git a/src/lv_objx/lv_bar.c b/src/lv_objx/lv_bar.c index 07db53239..078d7ce8f 100644 --- a/src/lv_objx/lv_bar.c +++ b/src/lv_objx/lv_bar.c @@ -518,9 +518,9 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mo lv_coord_t anim_start_value_end_x = (int32_t)((int32_t)anim_length * (ext->start_value_anim.anim_end - ext->min_value)) / range; - anim_start_value_x = (((anim_start_value_end_x - anim_start_value_start_x) * ext->start_value_anim.anim_state) >> LV_BAR_ANIM_STATE_NORM); + anim_start_value_x = (((anim_start_value_end_x - anim_start_value_start_x) * ext->start_value_anim.anim_state) / LV_BAR_ANIM_STATE_END); - if(anim_start_value_x < 0) + if(anim_start_value_end_x < anim_start_value_start_x) anim_start_value_x += anim_start_value_start_x; } else #endif @@ -535,9 +535,9 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mo lv_coord_t anim_cur_value_end_x = (int32_t)((int32_t)anim_length * (ext->cur_value_anim.anim_end - ext->min_value)) / range; - anim_cur_value_x = (((anim_cur_value_end_x - anim_cur_value_start_x) * ext->cur_value_anim.anim_state) >> LV_BAR_ANIM_STATE_NORM); + anim_cur_value_x = (((anim_cur_value_end_x - anim_cur_value_start_x) * ext->cur_value_anim.anim_state) / LV_BAR_ANIM_STATE_END); - if(anim_cur_value_x < 0) + if(anim_cur_value_end_x < anim_cur_value_start_x) anim_cur_value_x += anim_cur_value_start_x; } else #endif