/** * Called periodically to handle the input devices * @param param unused */ static void indev_proc_task(void * param) { (void)param; LV_LOG_TRACE("indev task started"); lv_indev_data_t data; lv_indev_t * i; i = lv_indev_next(NULL); /*Read and process all indevs*/ while(i) { indev_act = i; /*Handle reset query before processing the point*/ indev_proc_reset_query_handler(i); if(i->proc.disabled == 0) { bool more_to_read; do { /*Read the data*/ more_to_read = lv_indev_read(i, &data); indev_proc_reset_query_handler(i); /*The active object might deleted even in the read function*/ i->proc.state = data.state; if(i->proc.state == LV_INDEV_STATE_PR) { i->last_activity_time = lv_tick_get(); } if(i->driver.type == LV_INDEV_TYPE_POINTER) { indev_pointer_proc(i, &data); } else if(i->driver.type == LV_INDEV_TYPE_KEYPAD) { indev_keypad_proc(i, &data); } else if(i->driver.type == LV_INDEV_TYPE_ENCODER) { indev_encoder_proc(i, &data); } else if(i->driver.type == LV_INDEV_TYPE_BUTTON) { indev_button_proc(i, &data); } /*Handle reset query if it happened in during processing*/ indev_proc_reset_query_handler(i); } while(more_to_read); } i = lv_indev_next(i); /*Go to the next indev*/ } indev_act = NULL; /*End of indev processing, so no act indev*/ LV_LOG_TRACE("indev task finished"); }
/** * Get the elapsed milliseconds science a previous time stamp * @param prev_tick a previous time stamp (return value of systick_get() ) * @return the elapsed milliseconds since 'prev_tick' */ uint32_t lv_tick_elaps(uint32_t prev_tick) { uint32_t act_time = lv_tick_get(); /*If there is no overflow in sys_time simple subtract*/ if(act_time >= prev_tick) { prev_tick = act_time - prev_tick; } else { prev_tick = UINT32_MAX - prev_tick + 1; prev_tick += act_time; } return prev_tick; }
/** * Create a new lv_task * @param task a function which is the task itself * @param period call period in ms unit * @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped) * @param param free parameter * @return pointer to the new task */ lv_task_t* lv_task_create(void (*task) (void *), uint32_t period, lv_task_prio_t prio, void * param) { lv_task_t* new_lv_task; new_lv_task = lv_ll_ins_head(&lv_task_ll); lv_mem_assert(new_lv_task); new_lv_task->period = period; new_lv_task->task = task; new_lv_task->prio = prio; new_lv_task->param = param; new_lv_task->once = 0; new_lv_task->last_run = lv_tick_get(); return new_lv_task; }
/** * Execute task if its the priority is appropriate * @param lv_task_p pointer to lv_task * @param prio_act the current priority * @return true: execute, false: not executed */ static bool lv_task_exec (lv_task_t* lv_task_p, lv_task_prio_t prio_act) { bool exec = false; /*Execute lv_task if its prio is 'prio_act'*/ if(lv_task_p->prio == prio_act) { /*Execute if at least 'period' time elapsed*/ uint32_t elp = lv_tick_elaps(lv_task_p->last_run); if(elp >= lv_task_p->period) { lv_task_p->last_run = lv_tick_get(); lv_task_p->task(lv_task_p->param); /*Delete if it was a one shot lv_task*/ if(lv_task_p->once != 0) lv_task_del(lv_task_p); exec = true; } } return exec; }
/** * Call it periodically to handle lv_tasks. */ inline void LV_ATTRIBUTE_TASK_HANDLER lv_task_handler(void) { static uint32_t idle_period_start = 0; static uint32_t handler_start = 0; static uint32_t busy_time = 0; if(lv_task_run == false) return; handler_start = lv_tick_get(); lv_task_t* lv_task_prio_a[LV_TASK_PRIO_NUM]; /*Lists for all prio.*/ lv_task_prio_t prio_act; bool prio_reset = false; /*Used to go back to the highest priority*/ lv_task_t* lv_task_next; /*Init. the lists*/ for(prio_act = LV_TASK_PRIO_LOWEST; prio_act <= LV_TASK_PRIO_HIGHEST; prio_act++) { lv_task_prio_a[prio_act] = lv_ll_get_head(&lv_task_ll); } /*Handle the lv_tasks on all priority*/ for(prio_act = LV_TASK_PRIO_HIGHEST; prio_act > LV_TASK_PRIO_OFF; prio_act --) { /*Reset the prio. if necessary*/ if(prio_reset != false) { prio_reset = false; prio_act = LV_TASK_PRIO_HIGHEST; /*Go again with highest prio */ } /* Read all lv_task on 'prio_act' but stop on 'prio_reset' */ while(lv_task_prio_a[prio_act] != NULL && prio_reset == false) { /* Get the next task. (Invalid pointer if a lv_task deletes itself)*/ lv_task_next = lv_ll_get_next(&lv_task_ll, lv_task_prio_a[prio_act]); /*Execute the current lv_task*/ bool executed = lv_task_exec(lv_task_prio_a[prio_act], prio_act); if(executed != false) { /*If the task is executed*/ /* During the execution higher priority lv_tasks * can be ready, so reset the priority if it is not highest*/ if(prio_act != LV_TASK_PRIO_HIGHEST) { prio_reset = true; } } lv_task_prio_a[prio_act] = lv_task_next; /*Load the next task*/ } /*Reset higher priority lists on 'prio_reset' query*/ if(prio_reset != false) { for(prio_act = prio_act + 1; prio_act <= LV_TASK_PRIO_HIGHEST; prio_act++) { lv_task_prio_a[prio_act] = lv_ll_get_head(&lv_task_ll); } } } busy_time += lv_tick_elaps(handler_start); uint32_t idle_period_time = lv_tick_elaps(idle_period_start); if(idle_period_time >= IDLE_MEAS_PERIOD) { idle_last = (uint32_t)((uint32_t)busy_time * 100) / IDLE_MEAS_PERIOD; /*Calculate the busy percentage*/ idle_last = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/ busy_time = 0; idle_period_start = lv_tick_get(); } }
/** * Reset a lv_task. * It will be called the previously set period milliseconds later. * @param lv_task_p pointer to a lv_task. */ void lv_task_reset(lv_task_t* lv_task_p) { lv_task_p->last_run = lv_tick_get(); }
/** * Make a lv_task ready. It will not wait its period. * @param lv_task_p pointer to a lv_task. */ void lv_task_ready(lv_task_t* lv_task_p) { lv_task_p->last_run = lv_tick_get() - lv_task_p->period - 1; }
/** * Reset the long press state of an input device * @param indev pointer to an input device */ void lv_indev_reset_lpr(lv_indev_t * indev) { indev->proc.long_pr_sent = 0; indev->proc.longpr_rep_timestamp = lv_tick_get(); indev->proc.pr_timestamp = lv_tick_get(); }
/** * Init. the animation module */ void lv_anim_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_REFR_PERIOD, LV_TASK_PRIO_MID, NULL); }