mirror of
https://github.com/Valeh2012/PersonalVotingMachine
synced 2025-12-08 10:05:12 +02:00
first commit
This commit is contained in:
473
extended-setup/components/lvgl/src/lv_misc/lv_anim.c
Normal file
473
extended-setup/components/lvgl/src/lv_misc/lv_anim.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/**
|
||||
* @file anim.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_anim.h"
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "lv_task.h"
|
||||
#include "lv_math.h"
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
#include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_ANIM_RESOLUTION 1024
|
||||
#define LV_ANIM_RES_SHIFT 10
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void anim_task(lv_task_t * param);
|
||||
static bool anim_ready_handler(lv_anim_t * a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static uint32_t last_task_run;
|
||||
static bool anim_list_changed;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init. the animation module
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an animation variable.
|
||||
* E.g.:
|
||||
* lv_anim_t a;
|
||||
* lv_anim_init(&a);
|
||||
* lv_anim_set_...(&a);
|
||||
* lv_anim_craete(&a);
|
||||
* @param a pointer to an `lv_anim_t` variable to initialize
|
||||
*/
|
||||
void lv_anim_init(lv_anim_t * a)
|
||||
{
|
||||
memset(a, 0, sizeof(lv_anim_t));
|
||||
a->time = 500;
|
||||
a->start = 0;
|
||||
a->end = 100;
|
||||
a->path_cb = lv_anim_path_linear;
|
||||
}
|
||||
/**
|
||||
* Create an animation
|
||||
* @param a an initialized 'anim_t' variable. Not required after call.
|
||||
*/
|
||||
void lv_anim_create(lv_anim_t * a)
|
||||
{
|
||||
LV_LOG_TRACE("animation create started")
|
||||
/* Do not let two animations for the same 'var' with the same 'fp'*/
|
||||
if(a->exec_cb != NULL) lv_anim_del(a->var, a->exec_cb); /*fp == NULL would delete all animations of var*/
|
||||
|
||||
/*Add the new animation to the animation linked list*/
|
||||
lv_anim_t * new_anim = lv_ll_ins_head(&LV_GC_ROOT(_lv_anim_ll));
|
||||
lv_mem_assert(new_anim);
|
||||
if(new_anim == NULL) return;
|
||||
|
||||
/*Initialize the animation descriptor*/
|
||||
a->playback_now = 0;
|
||||
memcpy(new_anim, a, sizeof(lv_anim_t));
|
||||
|
||||
/*Set the start value*/
|
||||
if(new_anim->exec_cb) new_anim->exec_cb(new_anim->var, new_anim->start);
|
||||
|
||||
/* Creating an animation changed the linked list.
|
||||
* It's important if it happens in a ready callback. (see `anim_task`)*/
|
||||
anim_list_changed = true;
|
||||
|
||||
LV_LOG_TRACE("animation created")
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an animation of a variable with a given animator function
|
||||
* @param var pointer to variable
|
||||
* @param exec_cb a function pointer which is animating 'var',
|
||||
* or NULL to delete all the animations of 'var'
|
||||
* @return true: at least 1 animation is deleted, false: no animation is deleted
|
||||
*/
|
||||
bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb)
|
||||
{
|
||||
lv_anim_t * a;
|
||||
lv_anim_t * a_next;
|
||||
bool del = false;
|
||||
a = lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
|
||||
while(a != NULL) {
|
||||
/*'a' might be deleted, so get the next object while 'a' is valid*/
|
||||
a_next = lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a);
|
||||
|
||||
if(a->var == var && (a->exec_cb == exec_cb || exec_cb == NULL)) {
|
||||
lv_ll_rem(&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
|
||||
the linked list*/
|
||||
del = true;
|
||||
}
|
||||
|
||||
a = a_next;
|
||||
}
|
||||
|
||||
return del;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of currently running animations
|
||||
* @return the number of running animations
|
||||
*/
|
||||
uint16_t lv_anim_count_running(void)
|
||||
{
|
||||
uint16_t cnt = 0;
|
||||
lv_anim_t * a;
|
||||
LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) cnt++;
|
||||
|
||||
return cnt++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the time of an animation with a given speed and the start and end values
|
||||
* @param speed speed of animation in unit/sec
|
||||
* @param start start value of the animation
|
||||
* @param end end value of the animation
|
||||
* @return the required time [ms] for the animation with the given parameters
|
||||
*/
|
||||
uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation applying linear characteristic
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_linear(const lv_anim_t * a)
|
||||
{
|
||||
/*Calculate the current step*/
|
||||
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 = (int32_t)step * (a->end - a->start);
|
||||
new_value = new_value >> LV_ANIM_RES_SHIFT;
|
||||
new_value += a->start;
|
||||
|
||||
return (lv_anim_value_t)new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation slowing down the start phase
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_ease_in(const lv_anim_t * a)
|
||||
{
|
||||
/*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;
|
||||
|
||||
int32_t step = lv_bezier3(t, 0, 1, 1, 1024);
|
||||
|
||||
int32_t new_value;
|
||||
new_value = (int32_t)step * (a->end - a->start);
|
||||
new_value = new_value >> 10;
|
||||
new_value += a->start;
|
||||
|
||||
return (lv_anim_value_t)new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation slowing down the end phase
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_ease_out(const lv_anim_t * a)
|
||||
{
|
||||
/*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;
|
||||
|
||||
int32_t step = lv_bezier3(t, 0, 1023, 1023, 1024);
|
||||
|
||||
int32_t new_value;
|
||||
new_value = (int32_t)step * (a->end - a->start);
|
||||
new_value = new_value >> 10;
|
||||
new_value += a->start;
|
||||
|
||||
return (lv_anim_value_t)new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation applying an "S" characteristic (cosine)
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_t * a)
|
||||
{
|
||||
/*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;
|
||||
|
||||
int32_t step = lv_bezier3(t, 0, 100, 924, 1024);
|
||||
|
||||
int32_t new_value;
|
||||
new_value = (int32_t)step * (a->end - a->start);
|
||||
new_value = new_value >> 10;
|
||||
new_value += a->start;
|
||||
|
||||
return (lv_anim_value_t)new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation with overshoot at the end
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_overshoot(const lv_anim_t * a)
|
||||
{
|
||||
/*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;
|
||||
|
||||
int32_t step = lv_bezier3(t, 0, 600, 1300, 1024);
|
||||
|
||||
int32_t new_value;
|
||||
new_value = (int32_t)step * (a->end - a->start);
|
||||
new_value = new_value >> 10;
|
||||
new_value += a->start;
|
||||
|
||||
return (lv_anim_value_t)new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation with 3 bounces
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a)
|
||||
{
|
||||
/*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;
|
||||
|
||||
int32_t diff = (a->end - a->start);
|
||||
|
||||
/*3 bounces has 5 parts: 3 down and 2 up. One part is t / 5 long*/
|
||||
|
||||
if(t < 408) {
|
||||
/*Go down*/
|
||||
t = (t * 2500) >> 10; /*[0..1024] range*/
|
||||
} else if(t >= 408 && t < 614) {
|
||||
/*First bounce back*/
|
||||
t -= 408;
|
||||
t = t * 5; /*to [0..1024] range*/
|
||||
t = 1024 - t;
|
||||
diff = diff / 6;
|
||||
} else if(t >= 614 && t < 819) {
|
||||
/*Fall back*/
|
||||
t -= 614;
|
||||
t = t * 5; /*to [0..1024] range*/
|
||||
diff = diff / 6;
|
||||
} else if(t >= 819 && t < 921) {
|
||||
/*Second bounce back*/
|
||||
t -= 819;
|
||||
t = t * 10; /*to [0..1024] range*/
|
||||
t = 1024 - t;
|
||||
diff = diff / 16;
|
||||
} else if(t >= 921 && t <= 1024) {
|
||||
/*Fall back*/
|
||||
t -= 921;
|
||||
t = t * 10; /*to [0..1024] range*/
|
||||
diff = diff / 16;
|
||||
}
|
||||
|
||||
if(t > 1024) t = 1024;
|
||||
|
||||
int32_t step = lv_bezier3(t, 1024, 1024, 800, 0);
|
||||
|
||||
int32_t new_value;
|
||||
new_value = (int32_t)step * diff;
|
||||
new_value = new_value >> 10;
|
||||
new_value = a->end - new_value;
|
||||
|
||||
return (lv_anim_value_t)new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation applying step characteristic.
|
||||
* (Set end value on the end of the animation)
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_step(const lv_anim_t * a)
|
||||
{
|
||||
if(a->act_time >= a->time)
|
||||
return a->end;
|
||||
else
|
||||
return a->start;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Periodically handle the animations.
|
||||
* @param param unused
|
||||
*/
|
||||
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);
|
||||
|
||||
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
|
||||
* happened in `anim_ready_handler` which could make this linked list reading corrupt
|
||||
* because the list is changed meanwhile
|
||||
*/
|
||||
anim_list_changed = false;
|
||||
|
||||
if(!a->has_run) {
|
||||
a->has_run = 1; /*The list readying might be reseted so need to know which anim has run already*/
|
||||
a->act_time += elaps;
|
||||
if(a->act_time >= 0) {
|
||||
if(a->act_time > a->time) a->act_time = a->time;
|
||||
|
||||
int32_t new_value;
|
||||
new_value = a->path_cb(a);
|
||||
|
||||
/*Apply the calculated value*/
|
||||
if(a->exec_cb) a->exec_cb(a->var, new_value);
|
||||
|
||||
/*If the time is elapsed the animation is ready*/
|
||||
if(a->act_time >= a->time) {
|
||||
anim_ready_handler(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the linked list changed due to anim. delete then it's not safe to continue
|
||||
* the reading of the list from here -> start from the head*/
|
||||
if(anim_list_changed)
|
||||
a = lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
|
||||
else
|
||||
a = lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a);
|
||||
}
|
||||
|
||||
last_task_run = lv_tick_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return true: animation delete occurred nnd the `LV_GC_ROOT(_lv_anim_ll)` has changed
|
||||
* */
|
||||
static bool anim_ready_handler(lv_anim_t * a)
|
||||
{
|
||||
|
||||
/*Delete the animation if
|
||||
* - no repeat and no play back (simple one shot animation)
|
||||
* - no repeat, play back is enabled and play back is ready */
|
||||
if((a->repeat == 0 && a->playback == 0) || (a->repeat == 0 && a->playback == 1 && a->playback_now == 1)) {
|
||||
|
||||
/*Create copy from the animation and delete the animation from the list.
|
||||
* This way the `ready_cb` will see the animations like it's animation is ready deleted*/
|
||||
lv_anim_t a_tmp;
|
||||
memcpy(&a_tmp, a, sizeof(lv_anim_t));
|
||||
lv_ll_rem(&LV_GC_ROOT(_lv_anim_ll), a);
|
||||
lv_mem_free(a);
|
||||
anim_list_changed = true;
|
||||
|
||||
/* Call the callback function at the end*/
|
||||
if(a_tmp.ready_cb != NULL) a_tmp.ready_cb(&a_tmp);
|
||||
}
|
||||
/*If the animation is not deleted then restart it*/
|
||||
else {
|
||||
a->act_time = -a->repeat_pause; /*Restart the animation*/
|
||||
/*Swap the start and end values in play back mode*/
|
||||
if(a->playback != 0) {
|
||||
/*If now turning back use the 'playback_pause*/
|
||||
if(a->playback_now == 0) a->act_time = -a->playback_pause;
|
||||
|
||||
/*Toggle the play back state*/
|
||||
a->playback_now = a->playback_now == 0 ? 1 : 0;
|
||||
/*Swap the start and end values*/
|
||||
int32_t tmp;
|
||||
tmp = a->start;
|
||||
a->start = a->end;
|
||||
a->end = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return anim_list_changed;
|
||||
}
|
||||
#endif
|
||||
331
extended-setup/components/lvgl/src/lv_misc/lv_anim.h
Normal file
331
extended-setup/components/lvgl/src/lv_misc/lv_anim.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/**
|
||||
* @file anim.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANIM_H
|
||||
#define ANIM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Can be used to indicate if animations are enabled or disabled in a case*/
|
||||
enum {
|
||||
LV_ANIM_OFF,
|
||||
LV_ANIM_ON,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_anim_enable_t;
|
||||
|
||||
/** Type of the animated value*/
|
||||
typedef lv_coord_t lv_anim_value_t;
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
|
||||
struct _lv_anim_t;
|
||||
|
||||
/** Generic prototype of "animator" functions.
|
||||
* First parameter is the variable to animate.
|
||||
* Second parameter is the value to set.
|
||||
* Compatible with `lv_xxx_set_yyy(obj, value)` functions
|
||||
* The `x` in `_xcb_t` means its not a fully generic prototype because
|
||||
* it doesn't receive `lv_anim_t *` as its first argument*/
|
||||
typedef void (*lv_anim_exec_xcb_t)(void *, lv_anim_value_t);
|
||||
|
||||
/** Same as `lv_anim_exec_xcb_t` but receives `lv_anim_t *` as the first parameter.
|
||||
* It's more consistent but less convenient. Might be used by binding generator functions.*/
|
||||
typedef void (*lv_anim_custom_exec_cb_t)(struct _lv_anim_t *, lv_anim_value_t);
|
||||
|
||||
/** Get the current value during an animation*/
|
||||
typedef lv_anim_value_t (*lv_anim_path_cb_t)(const struct _lv_anim_t *);
|
||||
|
||||
/** Callback to call when the animation is ready*/
|
||||
typedef void (*lv_anim_ready_cb_t)(struct _lv_anim_t *);
|
||||
|
||||
/** Describes an animation*/
|
||||
typedef struct _lv_anim_t
|
||||
{
|
||||
void * var; /**<Variable to animate*/
|
||||
lv_anim_exec_xcb_t exec_cb; /**< Function to execute to animate*/
|
||||
lv_anim_path_cb_t path_cb; /**< Function to get the steps of animations*/
|
||||
lv_anim_ready_cb_t ready_cb; /**< Call it when the animation is ready*/
|
||||
int32_t start; /**< Start value*/
|
||||
int32_t end; /**< End value*/
|
||||
uint16_t time; /**< Animation time in ms*/
|
||||
int16_t act_time; /**< Current time in animation. Set to negative to make delay.*/
|
||||
uint16_t playback_pause; /**< Wait before play back*/
|
||||
uint16_t repeat_pause; /**< Wait before repeat*/
|
||||
#if LV_USE_USER_DATA
|
||||
lv_anim_user_data_t user_data; /**< Custom user data*/
|
||||
#endif
|
||||
|
||||
uint8_t playback : 1; /**< When the animation is ready play it back*/
|
||||
uint8_t repeat : 1; /**< Repeat the animation infinitely*/
|
||||
/*Animation system use these - user shouldn't set*/
|
||||
uint8_t playback_now : 1; /**< Play back is in progress*/
|
||||
uint32_t has_run : 1; /**< Indicates the animation has run in this round*/
|
||||
} lv_anim_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init. the animation module
|
||||
*/
|
||||
void lv_anim_core_init(void);
|
||||
|
||||
/**
|
||||
* Initialize an animation variable.
|
||||
* E.g.:
|
||||
* lv_anim_t a;
|
||||
* lv_anim_init(&a);
|
||||
* lv_anim_set_...(&a);
|
||||
* lv_anim_create(&a);
|
||||
* @param a pointer to an `lv_anim_t` variable to initialize
|
||||
*/
|
||||
void lv_anim_init(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Set a variable to animate function to execute on `var`
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param var pointer to a variable to animate
|
||||
* @param exec_cb a function to execute.
|
||||
* LittelvGL's built-in functions can be used.
|
||||
* E.g. lv_obj_set_x
|
||||
*/
|
||||
static inline void lv_anim_set_exec_cb(lv_anim_t * a, void * var, lv_anim_exec_xcb_t exec_cb)
|
||||
{
|
||||
a->var = var;
|
||||
a->exec_cb = exec_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the duration and delay of an animation
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param duration duration of the animation in milliseconds
|
||||
* @param delay delay before the animation in milliseconds
|
||||
*/
|
||||
static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, uint16_t delay)
|
||||
{
|
||||
a->time = duration;
|
||||
a->act_time = -delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start and end values of an animation
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param start the start value
|
||||
* @param end the end value
|
||||
*/
|
||||
static inline void lv_anim_set_values(lv_anim_t * a, lv_anim_value_t start, lv_anim_value_t end)
|
||||
{
|
||||
a->start = start;
|
||||
a->end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to `lv_anim_set_var_and_cb` but `lv_anim_custom_exec_cb_t` receives
|
||||
* `lv_anim_t * ` as its first parameter instead of `void *`.
|
||||
* This function might be used when LittlevGL is binded to other languages because
|
||||
* it's more consistent to have `lv_anim_t *` as first parameter.
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param exec_cb a function to execute.
|
||||
*/
|
||||
static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
|
||||
{
|
||||
a->var = a;
|
||||
a->exec_cb = (lv_anim_exec_xcb_t)exec_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path (curve) of the animation.
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @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_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb)
|
||||
{
|
||||
a->path_cb = path_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function call when the animation is ready
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param ready_cb a function call when the animation is ready
|
||||
*/
|
||||
static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_cb)
|
||||
{
|
||||
a->ready_cb = ready_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the animation to play back to when the forward direction is ready
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param wait_time time in milliseconds to wait before starting the back direction
|
||||
*/
|
||||
static inline void lv_anim_set_playback(lv_anim_t * a, uint16_t wait_time)
|
||||
{
|
||||
a->playback = 1;
|
||||
a->playback_pause = wait_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable playback. (Disabled after `lv_anim_init()`)
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
*/
|
||||
static inline void lv_anim_clear_playback(lv_anim_t * a)
|
||||
{
|
||||
a->playback = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the animation to start again when ready.
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param wait_time time in milliseconds to wait before starting the animation again
|
||||
*/
|
||||
static inline void lv_anim_set_repeat(lv_anim_t * a, uint16_t wait_time)
|
||||
{
|
||||
a->repeat = 1;
|
||||
a->repeat_pause = wait_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable repeat. (Disabled after `lv_anim_init()`)
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
*/
|
||||
static inline void lv_anim_clear_repeat(lv_anim_t * a)
|
||||
{
|
||||
a->repeat = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an animation
|
||||
* @param a an initialized 'anim_t' variable. Not required after call.
|
||||
*/
|
||||
void lv_anim_create(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Delete an animation of a variable with a given animator function
|
||||
* @param var pointer to variable
|
||||
* @param exec_cb a function pointer which is animating 'var',
|
||||
* or NULL to ignore it and delete all the animations of 'var
|
||||
* @return true: at least 1 animation is deleted, false: no animation is deleted
|
||||
*/
|
||||
bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb);
|
||||
|
||||
/**
|
||||
* Delete an aniamation by getting the animated variable from `a`.
|
||||
* Only animations with `exec_cb` will be deleted.
|
||||
* This function exist becasue it's logical that all anim functions receives an
|
||||
* `lv_anim_t` as their first parameter. It's not practical in C but might makes
|
||||
* the API more conequent and makes easier to genrate bindings.
|
||||
* @param a pointer to an animation.
|
||||
* @param exec_cb a function pointer which is animating 'var',
|
||||
* or NULL to ignore it and delete all the animations of 'var
|
||||
* @return true: at least 1 animation is deleted, false: no animation is deleted
|
||||
*/
|
||||
static inline bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
|
||||
{
|
||||
return lv_anim_del(a->var, (lv_anim_exec_xcb_t)exec_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of currently running animations
|
||||
* @return the number of running animations
|
||||
*/
|
||||
uint16_t lv_anim_count_running(void);
|
||||
|
||||
/**
|
||||
* Calculate the time of an animation with a given speed and the start and end values
|
||||
* @param speed speed of animation in unit/sec
|
||||
* @param start start value of the animation
|
||||
* @param end end value of the animation
|
||||
* @return the required time [ms] for the animation with the given parameters
|
||||
*/
|
||||
uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation applying linear characteristic
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_linear(const lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation slowing down the start phase
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_ease_in(const lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation slowing down the end phase
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_ease_out(const lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation applying an "S" characteristic (cosine)
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation with overshoot at the end
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_overshoot(const lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation with 3 bounces
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Calculate the current value of an animation applying step characteristic.
|
||||
* (Set end value on the end of the animation)
|
||||
* @param a pointer to an animation
|
||||
* @return the current value to set
|
||||
*/
|
||||
lv_anim_value_t lv_anim_path_step(const lv_anim_t * a);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_ANIMATION == 0*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_ANIM_H*/
|
||||
197
extended-setup/components/lvgl/src/lv_misc/lv_area.c
Normal file
197
extended-setup/components/lvgl/src/lv_misc/lv_area.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @file lv_area.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include "lv_area.h"
|
||||
#include "lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize an area
|
||||
* @param area_p pointer to an area
|
||||
* @param x1 left coordinate of the area
|
||||
* @param y1 top coordinate of the area
|
||||
* @param x2 right coordinate of the area
|
||||
* @param y2 bottom coordinate of the area
|
||||
*/
|
||||
void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2)
|
||||
{
|
||||
area_p->x1 = x1;
|
||||
area_p->y1 = y1;
|
||||
area_p->x2 = x2;
|
||||
area_p->y2 = y2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of an area
|
||||
* @param area_p pointer to an area
|
||||
* @param w the new width of the area (w == 1 makes x1 == x2)
|
||||
*/
|
||||
void lv_area_set_width(lv_area_t * area_p, lv_coord_t w)
|
||||
{
|
||||
area_p->x2 = area_p->x1 + w - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of an area
|
||||
* @param area_p pointer to an area
|
||||
* @param h the new height of the area (h == 1 makes y1 == y2)
|
||||
*/
|
||||
void lv_area_set_height(lv_area_t * area_p, lv_coord_t h)
|
||||
{
|
||||
area_p->y2 = area_p->y1 + h - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of an area (width and height will be kept)
|
||||
* @param area_p pointer to an area
|
||||
* @param x the new x coordinate of the area
|
||||
* @param y the new y coordinate of the area
|
||||
*/
|
||||
void lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(area_p);
|
||||
lv_coord_t h = lv_area_get_height(area_p);
|
||||
area_p->x1 = x;
|
||||
area_p->y1 = y;
|
||||
lv_area_set_width(area_p, w);
|
||||
lv_area_set_height(area_p, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with area of an area (x * y)
|
||||
* @param area_p pointer to an area
|
||||
* @return size of area
|
||||
*/
|
||||
uint32_t lv_area_get_size(const lv_area_t * area_p)
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
size = (uint32_t)(area_p->x2 - area_p->x1 + 1) * (area_p->y2 - area_p->y1 + 1);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the common parts of two areas
|
||||
* @param res_p pointer to an area, the result will be stored here
|
||||
* @param a1_p pointer to the first area
|
||||
* @param a2_p pointer to the second area
|
||||
* @return false: the two area has NO common parts, res_p is invalid
|
||||
*/
|
||||
bool lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p)
|
||||
{
|
||||
/* Get the smaller area from 'a1_p' and 'a2_p' */
|
||||
res_p->x1 = LV_MATH_MAX(a1_p->x1, a2_p->x1);
|
||||
res_p->y1 = LV_MATH_MAX(a1_p->y1, a2_p->y1);
|
||||
res_p->x2 = LV_MATH_MIN(a1_p->x2, a2_p->x2);
|
||||
res_p->y2 = LV_MATH_MIN(a1_p->y2, a2_p->y2);
|
||||
|
||||
/*If x1 or y1 greater then x2 or y2 then the areas union is empty*/
|
||||
bool union_ok = true;
|
||||
if((res_p->x1 > res_p->x2) || (res_p->y1 > res_p->y2)) {
|
||||
union_ok = false;
|
||||
}
|
||||
|
||||
return union_ok;
|
||||
}
|
||||
/**
|
||||
* Join two areas into a third which involves the other two
|
||||
* @param res_p pointer to an area, the result will be stored here
|
||||
* @param a1_p pointer to the first area
|
||||
* @param a2_p pointer to the second area
|
||||
*/
|
||||
void lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p)
|
||||
{
|
||||
a_res_p->x1 = LV_MATH_MIN(a1_p->x1, a2_p->x1);
|
||||
a_res_p->y1 = LV_MATH_MIN(a1_p->y1, a2_p->y1);
|
||||
a_res_p->x2 = LV_MATH_MAX(a1_p->x2, a2_p->x2);
|
||||
a_res_p->y2 = LV_MATH_MAX(a1_p->y2, a2_p->y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a point is on an area
|
||||
* @param a_p pointer to an area
|
||||
* @param p_p pointer to a point
|
||||
* @return false:the point is out of the area
|
||||
*/
|
||||
bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p)
|
||||
{
|
||||
bool is_on = false;
|
||||
|
||||
if((p_p->x >= a_p->x1 && p_p->x <= a_p->x2) && ((p_p->y >= a_p->y1 && p_p->y <= a_p->y2))) {
|
||||
is_on = true;
|
||||
}
|
||||
|
||||
return is_on;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two area has common parts
|
||||
* @param a1_p pointer to an area.
|
||||
* @param a2_p pointer to an other area
|
||||
* @return false: a1_p and a2_p has no common parts
|
||||
*/
|
||||
bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p)
|
||||
{
|
||||
if((a1_p->x1 <= a2_p->x2) && (a1_p->x2 >= a2_p->x1) && (a1_p->y1 <= a2_p->y2) && (a1_p->y2 >= a2_p->y1)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an area is fully on an other
|
||||
* @param ain_p pointer to an area which could be in 'aholder_p'
|
||||
* @param aholder pointer to an area which could involve 'ain_p'
|
||||
* @return
|
||||
*/
|
||||
bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
|
||||
{
|
||||
bool is_in = false;
|
||||
|
||||
if(ain_p->x1 >= aholder_p->x1 && ain_p->y1 >= aholder_p->y1 && ain_p->x2 <= aholder_p->x2 &&
|
||||
ain_p->y2 <= aholder_p->y2) {
|
||||
is_in = true;
|
||||
}
|
||||
|
||||
return is_in;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
176
extended-setup/components/lvgl/src/lv_misc/lv_area.h
Normal file
176
extended-setup/components/lvgl/src/lv_misc/lv_area.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @file lv_area.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_AREA_H
|
||||
#define LV_AREA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*To avoid overflow don't let the max ranges (reduce with 1000) */
|
||||
#define LV_COORD_MAX ((lv_coord_t)((uint32_t)((uint32_t)1 << (8 * sizeof(lv_coord_t) - 1)) - 1000))
|
||||
#define LV_COORD_MIN (-LV_COORD_MAX)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Represents a point on the screen.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
lv_coord_t x;
|
||||
lv_coord_t y;
|
||||
} lv_point_t;
|
||||
|
||||
/** Represents an area of the screen. */
|
||||
typedef struct
|
||||
{
|
||||
lv_coord_t x1;
|
||||
lv_coord_t y1;
|
||||
lv_coord_t x2;
|
||||
lv_coord_t y2;
|
||||
} lv_area_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize an area
|
||||
* @param area_p pointer to an area
|
||||
* @param x1 left coordinate of the area
|
||||
* @param y1 top coordinate of the area
|
||||
* @param x2 right coordinate of the area
|
||||
* @param y2 bottom coordinate of the area
|
||||
*/
|
||||
void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2);
|
||||
|
||||
/**
|
||||
* Copy an area
|
||||
* @param dest pointer to the destination area
|
||||
* @param src pointer to the source area
|
||||
*/
|
||||
inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(lv_area_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of an area
|
||||
* @param area_p pointer to an area
|
||||
* @return the width of the area (if x1 == x2 -> width = 1)
|
||||
*/
|
||||
static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
|
||||
{
|
||||
return area_p->x2 - area_p->x1 + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of an area
|
||||
* @param area_p pointer to an area
|
||||
* @return the height of the area (if y1 == y2 -> height = 1)
|
||||
*/
|
||||
static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p)
|
||||
{
|
||||
return area_p->y2 - area_p->y1 + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of an area
|
||||
* @param area_p pointer to an area
|
||||
* @param w the new width of the area (w == 1 makes x1 == x2)
|
||||
*/
|
||||
void lv_area_set_width(lv_area_t * area_p, lv_coord_t w);
|
||||
|
||||
/**
|
||||
* Set the height of an area
|
||||
* @param area_p pointer to an area
|
||||
* @param h the new height of the area (h == 1 makes y1 == y2)
|
||||
*/
|
||||
void lv_area_set_height(lv_area_t * area_p, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Set the position of an area (width and height will be kept)
|
||||
* @param area_p pointer to an area
|
||||
* @param x the new x coordinate of the area
|
||||
* @param y the new y coordinate of the area
|
||||
*/
|
||||
void lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Return with area of an area (x * y)
|
||||
* @param area_p pointer to an area
|
||||
* @return size of area
|
||||
*/
|
||||
uint32_t lv_area_get_size(const lv_area_t * area_p);
|
||||
|
||||
/**
|
||||
* Get the common parts of two areas
|
||||
* @param res_p pointer to an area, the result will be stored her
|
||||
* @param a1_p pointer to the first area
|
||||
* @param a2_p pointer to the second area
|
||||
* @return false: the two area has NO common parts, res_p is invalid
|
||||
*/
|
||||
bool lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p);
|
||||
|
||||
/**
|
||||
* Join two areas into a third which involves the other two
|
||||
* @param res_p pointer to an area, the result will be stored here
|
||||
* @param a1_p pointer to the first area
|
||||
* @param a2_p pointer to the second area
|
||||
*/
|
||||
void lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p);
|
||||
|
||||
/**
|
||||
* Check if a point is on an area
|
||||
* @param a_p pointer to an area
|
||||
* @param p_p pointer to a point
|
||||
* @return false:the point is out of the area
|
||||
*/
|
||||
bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p);
|
||||
|
||||
/**
|
||||
* Check if two area has common parts
|
||||
* @param a1_p pointer to an area.
|
||||
* @param a2_p pointer to an other area
|
||||
* @return false: a1_p and a2_p has no common parts
|
||||
*/
|
||||
bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
|
||||
|
||||
/**
|
||||
* Check if an area is fully on an other
|
||||
* @param ain_p pointer to an area which could be on aholder_p
|
||||
* @param aholder pointer to an area which could involve ain_p
|
||||
* @return
|
||||
*/
|
||||
bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
75
extended-setup/components/lvgl/src/lv_misc/lv_async.c
Normal file
75
extended-setup/components/lvgl/src/lv_misc/lv_async.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file lv_async.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_async.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_async_task_cb(lv_task_t *task);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data)
|
||||
{
|
||||
/*Allocate an info structure */
|
||||
lv_async_info_t *info = lv_mem_alloc(sizeof(lv_async_info_t));
|
||||
|
||||
if(info == NULL)
|
||||
return LV_RES_INV;
|
||||
|
||||
/* Create a new task */
|
||||
/* Use highest priority so that it will run before a refresh */
|
||||
lv_task_t *task = lv_task_create(lv_async_task_cb, 0, LV_TASK_PRIO_HIGHEST, info);
|
||||
|
||||
if(task == NULL) {
|
||||
lv_mem_free(info);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
info->cb = async_xcb;
|
||||
info->user_data = user_data;
|
||||
|
||||
/* Set the task's user data */
|
||||
task->user_data = info;
|
||||
lv_task_once(task);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_async_task_cb(lv_task_t *task)
|
||||
{
|
||||
lv_async_info_t *info = (lv_async_info_t *)task->user_data;
|
||||
|
||||
info->cb(info->user_data);
|
||||
|
||||
lv_mem_free(info);
|
||||
}
|
||||
62
extended-setup/components/lvgl/src/lv_misc/lv_async.h
Normal file
62
extended-setup/components/lvgl/src/lv_misc/lv_async.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @file lv_async.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_ASYNC_H
|
||||
#define LV_ASYNC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_task.h"
|
||||
#include "lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Type for async callback.
|
||||
*/
|
||||
typedef void (*lv_async_cb_t)(void *);
|
||||
|
||||
typedef struct _lv_async_info_t {
|
||||
lv_async_cb_t cb;
|
||||
void *user_data;
|
||||
} lv_async_info_t;
|
||||
|
||||
struct _lv_obj_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Call an asynchronous function the next time lv_task_handler() is run. This function is likely to return
|
||||
* **before** the call actually happens!
|
||||
* @param task_xcb a callback which is the task itself.
|
||||
* (the 'x' in the argument name indicates that its not a fully generic function because it not follows
|
||||
* the `func_name(object, callback, ...)` convention)
|
||||
* @param user_data custom parameter
|
||||
*/
|
||||
lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEMPL_H*/
|
||||
79
extended-setup/components/lvgl/src/lv_misc/lv_circ.c
Normal file
79
extended-setup/components/lvgl/src/lv_misc/lv_circ.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file lv_circ.c
|
||||
* Circle drawing algorithm (with Bresenham)
|
||||
* Only a 1/8 circle is calculated. Use CIRC_OCT1_X, CIRC_OCT1_Y macros to get
|
||||
* the other octets.
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_circ.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the circle drawing
|
||||
* @param c pointer to a point. The coordinates will be calculated here
|
||||
* @param tmp point to a variable. It will store temporary data
|
||||
* @param radius radius of the circle
|
||||
*/
|
||||
void lv_circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius)
|
||||
{
|
||||
c->x = radius;
|
||||
c->y = 0;
|
||||
*tmp = 1 - radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the circle drawing is ready or not
|
||||
* @param c same as in circ_init
|
||||
* @return true if the circle is not ready yet
|
||||
*/
|
||||
bool lv_circ_cont(lv_point_t * c)
|
||||
{
|
||||
return c->y <= c->x ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next point from the circle
|
||||
* @param c same as in circ_init. The next point stored here.
|
||||
* @param tmp same as in circ_init.
|
||||
*/
|
||||
void lv_circ_next(lv_point_t * c, lv_coord_t * tmp)
|
||||
{
|
||||
c->y++;
|
||||
|
||||
if(*tmp <= 0) {
|
||||
(*tmp) += 2 * c->y + 1; // Change in decision criterion for y -> y+1
|
||||
} else {
|
||||
c->x--;
|
||||
(*tmp) += 2 * (c->y - c->x) + 1; // Change for y -> y+1, x -> x-1
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
77
extended-setup/components/lvgl/src/lv_misc/lv_circ.h
Normal file
77
extended-setup/components/lvgl/src/lv_misc/lv_circ.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file lv_circ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CIRC_H
|
||||
#define LV_CIRC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_CIRC_OCT1_X(p) (p.x)
|
||||
#define LV_CIRC_OCT1_Y(p) (p.y)
|
||||
#define LV_CIRC_OCT2_X(p) (p.y)
|
||||
#define LV_CIRC_OCT2_Y(p) (p.x)
|
||||
#define LV_CIRC_OCT3_X(p) (-p.y)
|
||||
#define LV_CIRC_OCT3_Y(p) (p.x)
|
||||
#define LV_CIRC_OCT4_X(p) (-p.x)
|
||||
#define LV_CIRC_OCT4_Y(p) (p.y)
|
||||
#define LV_CIRC_OCT5_X(p) (-p.x)
|
||||
#define LV_CIRC_OCT5_Y(p) (-p.y)
|
||||
#define LV_CIRC_OCT6_X(p) (-p.y)
|
||||
#define LV_CIRC_OCT6_Y(p) (-p.x)
|
||||
#define LV_CIRC_OCT7_X(p) (p.y)
|
||||
#define LV_CIRC_OCT7_Y(p) (-p.x)
|
||||
#define LV_CIRC_OCT8_X(p) (p.x)
|
||||
#define LV_CIRC_OCT8_Y(p) (-p.y)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the circle drawing
|
||||
* @param c pointer to a point. The coordinates will be calculated here
|
||||
* @param tmp point to a variable. It will store temporary data
|
||||
* @param radius radius of the circle
|
||||
*/
|
||||
void lv_circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius);
|
||||
|
||||
/**
|
||||
* Test the circle drawing is ready or not
|
||||
* @param c same as in circ_init
|
||||
* @return true if the circle is not ready yet
|
||||
*/
|
||||
bool lv_circ_cont(lv_point_t * c);
|
||||
|
||||
/**
|
||||
* Get the next point from the circle
|
||||
* @param c same as in circ_init. The next point stored here.
|
||||
* @param tmp same as in circ_init.
|
||||
*/
|
||||
void lv_circ_next(lv_point_t * c, lv_coord_t * tmp);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
143
extended-setup/components/lvgl/src/lv_misc/lv_color.c
Normal file
143
extended-setup/components/lvgl/src/lv_misc/lv_color.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file lv_color.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert a HSV color to RGB
|
||||
* @param h hue [0..359]
|
||||
* @param s saturation [0..100]
|
||||
* @param v value [0..100]
|
||||
* @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
|
||||
*/
|
||||
lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
|
||||
{
|
||||
h = (uint32_t)((uint32_t)h * 255) / 360;
|
||||
s = (uint16_t)((uint16_t)s * 255) / 100;
|
||||
v = (uint16_t)((uint16_t)v * 255) / 100;
|
||||
|
||||
uint8_t r, g, b;
|
||||
|
||||
uint8_t region, remainder, p, q, t;
|
||||
|
||||
if(s == 0) {
|
||||
r = v;
|
||||
g = v;
|
||||
b = v;
|
||||
return lv_color_make(v, v, v);
|
||||
}
|
||||
|
||||
region = h / 43;
|
||||
remainder = (h - (region * 43)) * 6;
|
||||
|
||||
p = (v * (255 - s)) >> 8;
|
||||
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
||||
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
||||
|
||||
switch(region) {
|
||||
case 0:
|
||||
r = v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q;
|
||||
g = v;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p;
|
||||
g = v;
|
||||
b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p;
|
||||
g = q;
|
||||
b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = v;
|
||||
break;
|
||||
default:
|
||||
r = v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_color_t result = lv_color_make(r, g, b);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an RGB color to HSV
|
||||
* @param r red
|
||||
* @param g green
|
||||
* @param b blue
|
||||
* @return the given RGB color n HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
lv_color_hsv_t hsv;
|
||||
uint8_t rgbMin, rgbMax;
|
||||
|
||||
rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
|
||||
|
||||
hsv.v = rgbMax;
|
||||
if(hsv.v == 0) {
|
||||
hsv.h = 0;
|
||||
hsv.s = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
hsv.s = 255 * (long)(rgbMax - rgbMin) / hsv.v;
|
||||
if(hsv.s == 0) {
|
||||
hsv.h = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
if(rgbMax == r)
|
||||
hsv.h = 0 + 43 * (g - b) / (rgbMax - rgbMin);
|
||||
else if(rgbMax == g)
|
||||
hsv.h = 85 + 43 * (b - r) / (rgbMax - rgbMin);
|
||||
else
|
||||
hsv.h = 171 + 43 * (r - g) / (rgbMax - rgbMin);
|
||||
|
||||
return hsv;
|
||||
}
|
||||
459
extended-setup/components/lvgl/src/lv_misc/lv_color.h
Normal file
459
extended-setup/components/lvgl/src/lv_misc/lv_color.h
Normal file
@@ -0,0 +1,459 @@
|
||||
/**
|
||||
* @file lv_color.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_COLOR_H
|
||||
#define LV_COLOR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
/*Error checking*/
|
||||
#if LV_COLOR_DEPTH == 24
|
||||
#error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)"
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0
|
||||
#error "LV_COLOR_SCREEN_TRANSP requires LV_COLOR_DEPTH == 32. Set it in lv_conf.h"
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0
|
||||
#error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF)
|
||||
#define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
|
||||
#define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80)
|
||||
#define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00)
|
||||
#define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00)
|
||||
#define LV_COLOR_MAROON LV_COLOR_MAKE(0x80, 0x00, 0x00)
|
||||
#define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF, 0xFF, 0x00)
|
||||
#define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80, 0x80, 0x00)
|
||||
#define LV_COLOR_LIME LV_COLOR_MAKE(0x00, 0xFF, 0x00)
|
||||
#define LV_COLOR_GREEN LV_COLOR_MAKE(0x00, 0x80, 0x00)
|
||||
#define LV_COLOR_CYAN LV_COLOR_MAKE(0x00, 0xFF, 0xFF)
|
||||
#define LV_COLOR_AQUA LV_COLOR_CYAN
|
||||
#define LV_COLOR_TEAL LV_COLOR_MAKE(0x00, 0x80, 0x80)
|
||||
#define LV_COLOR_BLUE LV_COLOR_MAKE(0x00, 0x00, 0xFF)
|
||||
#define LV_COLOR_NAVY LV_COLOR_MAKE(0x00, 0x00, 0x80)
|
||||
#define LV_COLOR_MAGENTA LV_COLOR_MAKE(0xFF, 0x00, 0xFF)
|
||||
#define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80, 0x00, 0x80)
|
||||
#define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF, 0xA5, 0x00)
|
||||
|
||||
/**
|
||||
* Opacity percentages.
|
||||
*/
|
||||
enum {
|
||||
LV_OPA_TRANSP = 0,
|
||||
LV_OPA_0 = 0,
|
||||
LV_OPA_10 = 25,
|
||||
LV_OPA_20 = 51,
|
||||
LV_OPA_30 = 76,
|
||||
LV_OPA_40 = 102,
|
||||
LV_OPA_50 = 127,
|
||||
LV_OPA_60 = 153,
|
||||
LV_OPA_70 = 178,
|
||||
LV_OPA_80 = 204,
|
||||
LV_OPA_90 = 229,
|
||||
LV_OPA_100 = 255,
|
||||
LV_OPA_COVER = 255,
|
||||
};
|
||||
|
||||
#define LV_OPA_MIN 16 /*Opacities below this will be transparent*/
|
||||
#define LV_OPA_MAX 251 /*Opacities above this will fully cover*/
|
||||
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
#define LV_COLOR_SIZE 8
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
#define LV_COLOR_SIZE 8
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#define LV_COLOR_SIZE 16
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_COLOR_SIZE 32
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t blue : 1;
|
||||
uint8_t green : 1;
|
||||
uint8_t red : 1;
|
||||
uint8_t full : 1;
|
||||
} lv_color1_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t blue : 2;
|
||||
uint8_t green : 3;
|
||||
uint8_t red : 3;
|
||||
} ch;
|
||||
uint8_t full;
|
||||
} lv_color8_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
uint16_t blue : 5;
|
||||
uint16_t green : 6;
|
||||
uint16_t red : 5;
|
||||
#else
|
||||
uint16_t green_h : 3;
|
||||
uint16_t red : 5;
|
||||
uint16_t blue : 5;
|
||||
uint16_t green_l : 3;
|
||||
#endif
|
||||
} ch;
|
||||
uint16_t full;
|
||||
} lv_color16_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t blue;
|
||||
uint8_t green;
|
||||
uint8_t red;
|
||||
uint8_t alpha;
|
||||
} ch;
|
||||
uint32_t full;
|
||||
} lv_color32_t;
|
||||
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
typedef uint8_t lv_color_int_t;
|
||||
typedef lv_color1_t lv_color_t;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
typedef uint8_t lv_color_int_t;
|
||||
typedef lv_color8_t lv_color_t;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
typedef uint16_t lv_color_int_t;
|
||||
typedef lv_color16_t lv_color_t;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
typedef uint32_t lv_color_int_t;
|
||||
typedef lv_color32_t lv_color_t;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
|
||||
#endif
|
||||
|
||||
typedef uint8_t lv_opa_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t h;
|
||||
uint8_t s;
|
||||
uint8_t v;
|
||||
} lv_color_hsv_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*In color conversations:
|
||||
* - When converting to bigger color type the LSB weight of 1 LSB is calculated
|
||||
* E.g. 16 bit Red has 5 bits
|
||||
* 8 bit Red has 2 bits
|
||||
* ----------------------
|
||||
* 8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10
|
||||
*
|
||||
* - When calculating to smaller color type simply shift out the LSBs
|
||||
* E.g. 8 bit Red has 2 bits
|
||||
* 16 bit Red has 5 bits
|
||||
* ----------------------
|
||||
* Shift right with 5 - 3 = 2
|
||||
*/
|
||||
|
||||
static inline uint8_t lv_color_to1(lv_color_t color)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
return color.full;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
if((color.ch.red & 0x4) || (color.ch.green & 0x4) || (color.ch.blue & 0x2)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
if((color.ch.red & 0x10) || (color.ch.green & 0x20) || (color.ch.blue & 0x10)) {
|
||||
return 1;
|
||||
#else
|
||||
if((color.ch.red & 0x10) || (color.ch.green_h & 0x20) || (color.ch.blue & 0x10)) {
|
||||
return 1;
|
||||
#endif
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
if((color.ch.red & 0x80) || (color.ch.green & 0x80) || (color.ch.blue & 0x80)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint8_t lv_color_to8(lv_color_t color)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
if(color.full == 0)
|
||||
return 0;
|
||||
else
|
||||
return 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
return color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
lv_color8_t ret;
|
||||
ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/
|
||||
ret.ch.green = color.ch.green >> 3; /* 6 - 3 = 3*/
|
||||
ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/
|
||||
return ret.full;
|
||||
#else
|
||||
lv_color8_t ret;
|
||||
ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/
|
||||
ret.ch.green = color.ch.green_h; /* 6 - 3 = 3*/
|
||||
ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/
|
||||
return ret.full;
|
||||
#endif
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
lv_color8_t ret;
|
||||
ret.ch.red = color.ch.red >> 5; /* 8 - 3 = 5*/
|
||||
ret.ch.green = color.ch.green >> 5; /* 8 - 3 = 5*/
|
||||
ret.ch.blue = color.ch.blue >> 6; /* 8 - 2 = 6*/
|
||||
return ret.full;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint16_t lv_color_to16(lv_color_t color)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
if(color.full == 0)
|
||||
return 0;
|
||||
else
|
||||
return 0xFFFF;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
lv_color16_t ret;
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
ret.ch.red = color.ch.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
|
||||
ret.ch.green = color.ch.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
|
||||
ret.ch.blue = color.ch.blue * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
|
||||
#else
|
||||
ret.red = color.ch.red * 4;
|
||||
uint8_t g_tmp = color.ch.green * 9;
|
||||
ret.ch.green_h = (g_tmp & 0x1F) >> 3;
|
||||
ret.ch.green_l = g_tmp & 0x07;
|
||||
ret.ch.blue = color.ch.blue * 10;
|
||||
#endif
|
||||
return ret.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
return color.full;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
lv_color16_t ret;
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
ret.ch.red = color.ch.red >> 3; /* 8 - 5 = 3*/
|
||||
ret.ch.green = color.ch.green >> 2; /* 8 - 6 = 2*/
|
||||
ret.ch.blue = color.ch.blue >> 3; /* 8 - 5 = 3*/
|
||||
#else
|
||||
ret.ch.red = color.ch.red >> 3;
|
||||
ret.ch.green_h = (color.ch.green & 0xE0) >> 5;
|
||||
ret.ch.green_l = (color.ch.green & 0x1C) >> 2;
|
||||
ret.ch.blue = color.ch.blue >> 3;
|
||||
#endif
|
||||
return ret.full;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t lv_color_to32(lv_color_t color)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
if(color.full == 0)
|
||||
return 0;
|
||||
else
|
||||
return 0xFFFFFFFF;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
lv_color32_t ret;
|
||||
ret.ch.red = color.ch.red * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
|
||||
ret.ch.green = color.ch.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
|
||||
ret.ch.blue = color.ch.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
|
||||
ret.ch.alpha = 0xFF;
|
||||
return ret.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
lv_color32_t ret;
|
||||
ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.green = color.ch.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
|
||||
ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.alpha = 0xFF;
|
||||
return ret.full;
|
||||
#else
|
||||
lv_color32_t ret;
|
||||
ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.green = ((color.ch.green_h << 3) + color.ch.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
|
||||
ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.alpha = 0xFF;
|
||||
return ret.full;
|
||||
#endif
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
return color.full;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
|
||||
{
|
||||
lv_color_t ret;
|
||||
#if LV_COLOR_DEPTH != 1
|
||||
/*LV_COLOR_DEPTH == 8, 16 or 32*/
|
||||
ret.ch.red = (uint16_t)((uint16_t)c1.ch.red * mix + (c2.ch.red * (255 - mix))) >> 8;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
/*If swapped Green is in 2 parts*/
|
||||
uint16_t g_1 = (c1.ch.green_h << 3) + c1.ch.green_l;
|
||||
uint16_t g_2 = (c2.ch.green_h << 3) + c2.ch.green_l;
|
||||
uint16_t g_out = (uint16_t)((uint16_t)g_1 * mix + (g_2 * (255 - mix))) >> 8;
|
||||
ret.ch.green_h = g_out >> 3;
|
||||
ret.ch.green_l = g_out & 0x7;
|
||||
#else
|
||||
ret.ch.green = (uint16_t)((uint16_t)c1.ch.green * mix + (c2.ch.green * (255 - mix))) >> 8;
|
||||
#endif
|
||||
ret.ch.blue = (uint16_t)((uint16_t)c1.ch.blue * mix + (c2.ch.blue * (255 - mix))) >> 8;
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
ret.ch.alpha = 0xFF;
|
||||
#endif
|
||||
#else
|
||||
/*LV_COLOR_DEPTH == 1*/
|
||||
ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the brightness of a color
|
||||
* @param color a color
|
||||
* @return the brightness [0..255]
|
||||
*/
|
||||
static inline uint8_t lv_color_brightness(lv_color_t color)
|
||||
{
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(color);
|
||||
uint16_t bright = 3 * c32.ch.red + c32.ch.blue + 4 * c32.ch.green;
|
||||
return (uint16_t)bright >> 3;
|
||||
}
|
||||
|
||||
/* 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){(b8 >> 7 | g8 >> 7 | r8 >> 7)})
|
||||
static inline lv_color_t lv_color_make(int r8, int g8, int b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.full = (b8 >> 7 | g8 >> 7 | r8 >> 7);
|
||||
return color;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 6, g8 >> 5, r8 >> 5}})
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, int g8, int b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.blue = b8 >> 6;
|
||||
color.ch.green = g8 >> 5;
|
||||
color.ch.red = r8 >> 5;
|
||||
return color;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}})
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.blue = (uint16_t)(b8 >> 3);
|
||||
color.ch.green = (uint16_t)(g8 >> 2);
|
||||
color.ch.red = (uint16_t)(r8 >> 3);
|
||||
return color;
|
||||
}
|
||||
#else
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}})
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.green_h = (uint16_t)(g8 >> 5);
|
||||
color.ch.red = (uint16_t)(r8 >> 3);
|
||||
color.ch.blue = (uint16_t)(b8 >> 3);
|
||||
color.ch.green_l = (uint16_t)((g8 >> 2) & 0x7);
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.blue = b8;
|
||||
color.ch.green = g8;
|
||||
color.ch.red = r8;
|
||||
color.ch.alpha = 0xff;
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline lv_color_t lv_color_hex(uint32_t c)
|
||||
{
|
||||
return lv_color_make((uint8_t)((c >> 16) & 0xFF), (uint8_t)((c >> 8) & 0xFF), (uint8_t)(c & 0xFF));
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_color_hex3(uint32_t c)
|
||||
{
|
||||
return lv_color_make((uint8_t)(((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), (uint8_t)((c & 0xF0) | ((c & 0xF0) >> 4)),
|
||||
(uint8_t)((c & 0xF) | ((c & 0xF) << 4)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a HSV color to RGB
|
||||
* @param h hue [0..359]
|
||||
* @param s saturation [0..100]
|
||||
* @param v value [0..100]
|
||||
* @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
|
||||
*/
|
||||
lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
|
||||
|
||||
/**
|
||||
* Convert an RGB color to HSV
|
||||
* @param r red
|
||||
* @param g green
|
||||
* @param b blue
|
||||
* @return the given RGB color n HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*USE_COLOR*/
|
||||
641
extended-setup/components/lvgl/src/lv_misc/lv_fs.c
Normal file
641
extended-setup/components/lvgl/src/lv_misc/lv_fs.c
Normal file
@@ -0,0 +1,641 @@
|
||||
/**
|
||||
* @file lv_fs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_fs.h"
|
||||
#if LV_USE_FILESYSTEM
|
||||
|
||||
#include "lv_ll.h"
|
||||
#include <string.h>
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
#include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/* "free" is used as a function pointer (in lv_fs_drv_t).
|
||||
* We must make sure "free" was not defined to a platform specific
|
||||
* free function, otherwise compilation would fail.
|
||||
*/
|
||||
#ifdef free
|
||||
#undef free
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static const char * lv_fs_get_real_path(const char * path);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the File system interface
|
||||
*/
|
||||
void lv_fs_init(void)
|
||||
{
|
||||
lv_ll_init(&LV_GC_ROOT(_lv_drv_ll), sizeof(lv_fs_drv_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a drive is rady or not. If the `ready` function was not initialized `true` will be
|
||||
* returned.
|
||||
* @param letter letter of the drive
|
||||
* @return true: drive is ready; false: drive is not ready
|
||||
*/
|
||||
bool lv_fs_is_ready(char letter)
|
||||
{
|
||||
lv_fs_drv_t * drv = lv_fs_get_drv(letter);
|
||||
|
||||
if(drv == NULL) return false; /*An unknown driver in not ready*/
|
||||
|
||||
if(drv->ready_cb == NULL) return true; /*Assume the driver is always ready if no handler provided*/
|
||||
|
||||
return drv->ready_cb(drv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
|
||||
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mode)
|
||||
{
|
||||
file_p->drv = NULL;
|
||||
file_p->file_d = NULL;
|
||||
|
||||
if(path == NULL) return LV_FS_RES_INV_PARAM;
|
||||
|
||||
char letter = path[0];
|
||||
|
||||
file_p->drv = lv_fs_get_drv(letter);
|
||||
|
||||
if(file_p->drv == NULL) {
|
||||
file_p->file_d = NULL;
|
||||
return LV_FS_RES_NOT_EX;
|
||||
}
|
||||
|
||||
if(file_p->drv->ready_cb != NULL) {
|
||||
if(file_p->drv->ready_cb(file_p->drv) == false) {
|
||||
file_p->drv = NULL;
|
||||
file_p->file_d = NULL;
|
||||
return LV_FS_RES_HW_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
file_p->file_d = lv_mem_alloc(file_p->drv->file_size);
|
||||
lv_mem_assert(file_p->file_d);
|
||||
if(file_p->file_d == NULL) {
|
||||
file_p->drv = NULL;
|
||||
return LV_FS_RES_OUT_OF_MEM; /* Out of memory */
|
||||
}
|
||||
|
||||
if(file_p->drv->open_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
const char * real_path = lv_fs_get_real_path(path);
|
||||
lv_fs_res_t res = file_p->drv->open_cb(file_p->drv, file_p->file_d, real_path, mode);
|
||||
|
||||
if(res != LV_FS_RES_OK) {
|
||||
lv_mem_free(file_p->file_d);
|
||||
file_p->file_d = NULL;
|
||||
file_p->drv = NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an already opened file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p)
|
||||
{
|
||||
if(file_p->drv == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(file_p->drv->close_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = file_p->drv->close_cb(file_p->drv, file_p->file_d);
|
||||
|
||||
lv_mem_free(file_p->file_d); /*Clean up*/
|
||||
file_p->file_d = NULL;
|
||||
file_p->drv = NULL;
|
||||
file_p->file_d = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file
|
||||
* @param path path of the file to delete
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_remove(const char * path)
|
||||
{
|
||||
if(path == NULL) return LV_FS_RES_INV_PARAM;
|
||||
lv_fs_drv_t * drv = NULL;
|
||||
|
||||
char letter = path[0];
|
||||
|
||||
drv = lv_fs_get_drv(letter);
|
||||
if(drv == NULL) return LV_FS_RES_NOT_EX;
|
||||
if(drv->ready_cb != NULL) {
|
||||
if(drv->ready_cb(drv) == false) return LV_FS_RES_HW_ERR;
|
||||
}
|
||||
|
||||
if(drv->remove_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||
|
||||
const char * real_path = lv_fs_get_real_path(path);
|
||||
lv_fs_res_t res = drv->remove_cb(drv, real_path);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param buf pointer to a buffer where the read bytes are stored
|
||||
* @param btr Bytes To Read
|
||||
* @param br the number of real read bytes (Bytes Read). NULL if unused.
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br)
|
||||
{
|
||||
if(br != NULL) *br = 0;
|
||||
if(file_p->drv == NULL) return LV_FS_RES_INV_PARAM;
|
||||
if(file_p->drv->read_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||
|
||||
uint32_t br_tmp = 0;
|
||||
lv_fs_res_t res = file_p->drv->read_cb(file_p->drv, file_p->file_d, buf, btr, &br_tmp);
|
||||
if(br != NULL) *br = br_tmp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write into a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param buf pointer to a buffer with the bytes to write
|
||||
* @param btr Bytes To Write
|
||||
* @param br the number of real written bytes (Bytes Written). NULL if unused.
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw)
|
||||
{
|
||||
if(bw != NULL) *bw = 0;
|
||||
|
||||
if(file_p->drv == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(file_p->drv->write_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
uint32_t bw_tmp = 0;
|
||||
lv_fs_res_t res = file_p->drv->write_cb(file_p->drv, file_p->file_d, buf, btw, &bw_tmp);
|
||||
if(bw != NULL) *bw = bw_tmp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of the 'cursor' (read write pointer) in a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param pos the new position expressed in bytes index (0: start of file)
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos)
|
||||
{
|
||||
if(file_p->drv == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(file_p->drv->seek_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the position of the read write pointer
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param pos_p pointer to store the position of the read write pointer
|
||||
* @return LV_FS_RES_OK or any error from 'fs_res_t'
|
||||
*/
|
||||
lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos)
|
||||
{
|
||||
if(file_p->drv == NULL) {
|
||||
pos = 0;
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(file_p->drv->tell_cb == NULL) {
|
||||
pos = 0;
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = file_p->drv->tell_cb(file_p->drv, file_p->file_d, pos);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate the file size to the current position of the read write pointer
|
||||
* @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_fs_open )
|
||||
* @return LV_FS_RES_OK: no error, the file is read
|
||||
* any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_trunc(lv_fs_file_t * file_p)
|
||||
{
|
||||
if(file_p->drv == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(file_p->drv->tell_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = file_p->drv->trunc_cb(file_p->drv, file_p->file_d);
|
||||
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Give the size of a file bytes
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param size pointer to a variable to store the size
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_size(lv_fs_file_t * file_p, uint32_t * size)
|
||||
{
|
||||
if(file_p->drv == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(file_p->drv->size_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||
|
||||
if(size == NULL) return LV_FS_RES_INV_PARAM;
|
||||
|
||||
lv_fs_res_t res = file_p->drv->size_cb(file_p->drv, file_p->file_d, size);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a file
|
||||
* @param oldname path to the file
|
||||
* @param newname path with the new name
|
||||
* @return LV_FS_RES_OK or any error from 'fs_res_t'
|
||||
*/
|
||||
lv_fs_res_t lv_fs_rename(const char * oldname, const char * newname)
|
||||
{
|
||||
if(!oldname || !newname) return LV_FS_RES_INV_PARAM;
|
||||
|
||||
char letter = oldname[0];
|
||||
|
||||
lv_fs_drv_t * drv = lv_fs_get_drv(letter);
|
||||
|
||||
if(!drv) {
|
||||
return LV_FS_RES_NOT_EX;
|
||||
}
|
||||
|
||||
if(drv->ready_cb != NULL) {
|
||||
if(drv->ready_cb(drv) == false) {
|
||||
return LV_FS_RES_HW_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if(drv->rename_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||
|
||||
const char * old_real = lv_fs_get_real_path(oldname);
|
||||
const char * new_real = lv_fs_get_real_path(newname);
|
||||
|
||||
lv_fs_res_t res = drv->rename_cb(drv, old_real, new_real);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a 'fs_read_dir_t' variable for directory reading
|
||||
* @param rddir_p pointer to a 'fs_read_dir_t' variable
|
||||
* @param path path to a directory
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
|
||||
{
|
||||
if(path == NULL) return LV_FS_RES_INV_PARAM;
|
||||
|
||||
char letter = path[0];
|
||||
|
||||
rddir_p->drv = lv_fs_get_drv(letter);
|
||||
|
||||
if(rddir_p->drv == NULL) {
|
||||
rddir_p->dir_d = NULL;
|
||||
return LV_FS_RES_NOT_EX;
|
||||
}
|
||||
|
||||
rddir_p->dir_d = lv_mem_alloc(rddir_p->drv->rddir_size);
|
||||
lv_mem_assert(rddir_p->dir_d);
|
||||
if(rddir_p->dir_d == NULL) {
|
||||
rddir_p->dir_d = NULL;
|
||||
return LV_FS_RES_OUT_OF_MEM; /* Out of memory */
|
||||
}
|
||||
|
||||
if(rddir_p->drv->dir_open_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
const char * real_path = lv_fs_get_real_path(path);
|
||||
|
||||
lv_fs_res_t res = rddir_p->drv->dir_open_cb(rddir_p->drv, rddir_p->dir_d, real_path);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next filename form a directory.
|
||||
* The name of the directories will begin with '/'
|
||||
* @param rddir_p pointer to an initialized 'fs_read_dir_t' variable
|
||||
* @param fn pointer to a buffer to store the filename
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn)
|
||||
{
|
||||
if(rddir_p->drv == NULL || rddir_p->dir_d == NULL) {
|
||||
fn[0] = '\0';
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
if(rddir_p->drv->dir_read_cb == NULL) {
|
||||
return LV_FS_RES_NOT_IMP;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the directory reading
|
||||
* @param rddir_p pointer to an initialized 'fs_read_dir_t' variable
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p)
|
||||
{
|
||||
if(rddir_p->drv == NULL || rddir_p->dir_d == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
lv_fs_res_t res;
|
||||
|
||||
if(rddir_p->drv->dir_close_cb == NULL) {
|
||||
res = LV_FS_RES_NOT_IMP;
|
||||
} else {
|
||||
res = rddir_p->drv->dir_close_cb(rddir_p->drv, rddir_p->dir_d);
|
||||
}
|
||||
|
||||
lv_mem_free(rddir_p->dir_d); /*Clean up*/
|
||||
rddir_p->dir_d = NULL;
|
||||
rddir_p->drv = NULL;
|
||||
rddir_p->dir_d = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the free and total size of a driver in kB
|
||||
* @param letter the driver letter
|
||||
* @param total_p pointer to store the total size [kB]
|
||||
* @param free_p pointer to store the free size_cb [kB]
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_free_space(char letter, uint32_t * total_p, uint32_t * free_p)
|
||||
{
|
||||
lv_fs_drv_t * drv = lv_fs_get_drv(letter);
|
||||
|
||||
if(drv == NULL) {
|
||||
return LV_FS_RES_INV_PARAM;
|
||||
}
|
||||
|
||||
lv_fs_res_t res;
|
||||
|
||||
if(drv->free_space_cb == NULL) {
|
||||
res = LV_FS_RES_NOT_IMP;
|
||||
} else {
|
||||
uint32_t total_tmp = 0;
|
||||
uint32_t free_tmp = 0;
|
||||
res = drv->free_space_cb(drv, &total_tmp, &free_tmp);
|
||||
|
||||
if(total_p != NULL) *total_p = total_tmp;
|
||||
if(free_p != NULL) *free_p = free_tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a file system driver with default values.
|
||||
* It is used to surly have known values in the fields ant not memory junk.
|
||||
* After it you can set the fields.
|
||||
* @param drv pointer to driver variable to initialize
|
||||
*/
|
||||
void lv_fs_drv_init(lv_fs_drv_t * drv)
|
||||
{
|
||||
memset(drv, 0, sizeof(lv_fs_drv_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new drive
|
||||
* @param drv_p pointer to an lv_fs_drv_t structure which is inited with the
|
||||
* corresponding function pointers. The data will be copied so the variable can be local.
|
||||
*/
|
||||
void lv_fs_drv_register(lv_fs_drv_t * drv_p)
|
||||
{
|
||||
/*Save the new driver*/
|
||||
lv_fs_drv_t * new_drv;
|
||||
new_drv = lv_ll_ins_head(&LV_GC_ROOT(_lv_drv_ll));
|
||||
lv_mem_assert(new_drv);
|
||||
if(new_drv == NULL) return;
|
||||
|
||||
memcpy(new_drv, drv_p, sizeof(lv_fs_drv_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a pointer to a driver from its letter
|
||||
* @param letter the driver letter
|
||||
* @return pointer to a driver or NULL if not found
|
||||
*/
|
||||
lv_fs_drv_t * lv_fs_get_drv(char letter)
|
||||
{
|
||||
lv_fs_drv_t * drv;
|
||||
|
||||
LV_LL_READ(LV_GC_ROOT(_lv_drv_ll), drv)
|
||||
{
|
||||
if(drv->letter == letter) {
|
||||
return drv;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/**
|
||||
* Fill a buffer with the letters of existing drivers
|
||||
* @param buf buffer to store the letters ('\0' added after the last letter)
|
||||
* @return the buffer
|
||||
*/
|
||||
char * lv_fs_get_letters(char * buf)
|
||||
{
|
||||
lv_fs_drv_t * drv;
|
||||
uint8_t i = 0;
|
||||
|
||||
LV_LL_READ(LV_GC_ROOT(_lv_drv_ll), drv)
|
||||
{
|
||||
buf[i] = drv->letter;
|
||||
i++;
|
||||
}
|
||||
|
||||
buf[i] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the extension of the filename
|
||||
* @param fn string with a filename
|
||||
* @return pointer to the beginning extension or empty string if no extension
|
||||
*/
|
||||
const char * lv_fs_get_ext(const char * fn)
|
||||
{
|
||||
uint16_t i;
|
||||
for(i = strlen(fn); i > 0; i--) {
|
||||
if(fn[i] == '.') {
|
||||
return &fn[i + 1];
|
||||
} else if(fn[i] == '/' || fn[i] == '\\') {
|
||||
return ""; /*No extension if a '\' or '/' found*/
|
||||
}
|
||||
}
|
||||
|
||||
return ""; /*Empty string if no '.' in the file name. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Step up one level
|
||||
* @param path pointer to a file name
|
||||
* @return the truncated file name
|
||||
*/
|
||||
char * lv_fs_up(char * path)
|
||||
{
|
||||
uint16_t len = strlen(path);
|
||||
if(len == 0) return path;
|
||||
|
||||
len--; /*Go before the trailing '\0'*/
|
||||
|
||||
/*Ignore trailing '/' or '\'*/
|
||||
while(path[len] == '/' || path[len] == '\\') {
|
||||
path[len] = '\0';
|
||||
if(len > 0)
|
||||
len--;
|
||||
else
|
||||
return path;
|
||||
}
|
||||
|
||||
uint16_t i;
|
||||
for(i = len; i > 0; i--) {
|
||||
if(path[i] == '/' || path[i] == '\\') break;
|
||||
}
|
||||
|
||||
if(i > 0) path[i] = '\0';
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last element of a path (e.g. U:/folder/file -> file)
|
||||
* @param path a character sting with the path to search in
|
||||
* @return pointer to the beginning of the last element in the path
|
||||
*/
|
||||
const char * lv_fs_get_last(const char * path)
|
||||
{
|
||||
uint16_t len = strlen(path);
|
||||
if(len == 0) return path;
|
||||
|
||||
len--; /*Go before the trailing '\0'*/
|
||||
|
||||
/*Ignore trailing '/' or '\'*/
|
||||
while(path[len] == '/' || path[len] == '\\') {
|
||||
if(len > 0)
|
||||
len--;
|
||||
else
|
||||
return path;
|
||||
}
|
||||
|
||||
uint16_t i;
|
||||
for(i = len; i > 0; i--) {
|
||||
if(path[i] == '/' || path[i] == '\\') break;
|
||||
}
|
||||
|
||||
/*No '/' or '\' in the path so return with path itself*/
|
||||
if(i == 0) return path;
|
||||
|
||||
return &path[i + 1];
|
||||
}
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Leave the driver letters and / or \ letters from beginning of the path
|
||||
* @param path path string (E.g. S:/folder/file.txt)
|
||||
* @return pointer to the beginning of the real path (E.g. folder/file.txt)
|
||||
*/
|
||||
static const char * lv_fs_get_real_path(const char * path)
|
||||
{
|
||||
/* Example path: "S:/folder/file.txt"
|
||||
* Leave the letter and the : / \ characters*/
|
||||
|
||||
path++; /*Ignore the driver letter*/
|
||||
|
||||
while(*path != '\0') {
|
||||
if(*path == ':' || *path == '\\' || *path == '/') {
|
||||
path++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FILESYSTEM*/
|
||||
298
extended-setup/components/lvgl/src/lv_misc/lv_fs.h
Normal file
298
extended-setup/components/lvgl/src/lv_misc/lv_fs.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
* @file lv_fs.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FS_H
|
||||
#define LV_FS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_FILESYSTEM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_FS_MAX_FN_LENGTH 64
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/**
|
||||
* Errors in the filesystem module.
|
||||
*/
|
||||
enum {
|
||||
LV_FS_RES_OK = 0,
|
||||
LV_FS_RES_HW_ERR, /*Low level hardware error*/
|
||||
LV_FS_RES_FS_ERR, /*Error in the file system structure */
|
||||
LV_FS_RES_NOT_EX, /*Driver, file or directory is not exists*/
|
||||
LV_FS_RES_FULL, /*Disk full*/
|
||||
LV_FS_RES_LOCKED, /*The file is already opened*/
|
||||
LV_FS_RES_DENIED, /*Access denied. Check 'fs_open' modes and write protect*/
|
||||
LV_FS_RES_BUSY, /*The file system now can't handle it, try later*/
|
||||
LV_FS_RES_TOUT, /*Process time outed*/
|
||||
LV_FS_RES_NOT_IMP, /*Requested function is not implemented*/
|
||||
LV_FS_RES_OUT_OF_MEM, /*Not enough memory for an internal operation*/
|
||||
LV_FS_RES_INV_PARAM, /*Invalid parameter among arguments*/
|
||||
LV_FS_RES_UNKNOWN, /*Other unknown error*/
|
||||
};
|
||||
typedef uint8_t lv_fs_res_t;
|
||||
|
||||
/**
|
||||
* Filesystem mode.
|
||||
*/
|
||||
enum {
|
||||
LV_FS_MODE_WR = 0x01,
|
||||
LV_FS_MODE_RD = 0x02,
|
||||
};
|
||||
typedef uint8_t lv_fs_mode_t;
|
||||
|
||||
typedef struct _lv_fs_drv_t
|
||||
{
|
||||
char letter;
|
||||
uint16_t file_size;
|
||||
uint16_t rddir_size;
|
||||
bool (*ready_cb)(struct _lv_fs_drv_t * drv);
|
||||
|
||||
lv_fs_res_t (*open_cb)(struct _lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode);
|
||||
lv_fs_res_t (*close_cb)(struct _lv_fs_drv_t * drv, void * file_p);
|
||||
lv_fs_res_t (*remove_cb)(struct _lv_fs_drv_t * drv, const char * fn);
|
||||
lv_fs_res_t (*read_cb)(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
|
||||
lv_fs_res_t (*write_cb)(struct _lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
|
||||
lv_fs_res_t (*seek_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos);
|
||||
lv_fs_res_t (*tell_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
|
||||
lv_fs_res_t (*trunc_cb)(struct _lv_fs_drv_t * drv, void * file_p);
|
||||
lv_fs_res_t (*size_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
|
||||
lv_fs_res_t (*rename_cb)(struct _lv_fs_drv_t * drv, const char * oldname, const char * newname);
|
||||
lv_fs_res_t (*free_space_cb)(struct _lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p);
|
||||
|
||||
lv_fs_res_t (*dir_open_cb)(struct _lv_fs_drv_t * drv, void * rddir_p, const char * path);
|
||||
lv_fs_res_t (*dir_read_cb)(struct _lv_fs_drv_t * drv, void * rddir_p, char * fn);
|
||||
lv_fs_res_t (*dir_close_cb)(struct _lv_fs_drv_t * drv, void * rddir_p);
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
lv_fs_drv_user_data_t user_data; /**< Custom file user data */
|
||||
#endif
|
||||
} lv_fs_drv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void * file_d;
|
||||
lv_fs_drv_t * drv;
|
||||
} lv_fs_file_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void * dir_d;
|
||||
lv_fs_drv_t * drv;
|
||||
} lv_fs_dir_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the File system interface
|
||||
*/
|
||||
void lv_fs_init(void);
|
||||
|
||||
/**
|
||||
* Initialize a file system driver with default values.
|
||||
* It is used to surly have known values in the fields ant not memory junk.
|
||||
* After it you can set the fields.
|
||||
* @param drv pointer to driver variable to initialize
|
||||
*/
|
||||
void lv_fs_drv_init(lv_fs_drv_t * drv);
|
||||
|
||||
/**
|
||||
* Add a new drive
|
||||
* @param drv_p pointer to an lv_fs_drv_t structure which is inited with the
|
||||
* corresponding function pointers. The data will be copied so the variable can be local.
|
||||
*/
|
||||
void lv_fs_drv_register(lv_fs_drv_t * drv_p);
|
||||
|
||||
/**
|
||||
* Give a pointer to a driver from its letter
|
||||
* @param letter the driver letter
|
||||
* @return pointer to a driver or NULL if not found
|
||||
*/
|
||||
lv_fs_drv_t * lv_fs_get_drv(char letter);
|
||||
|
||||
/**
|
||||
* Test if a drive is rady or not. If the `ready` function was not initialized `true` will be
|
||||
* returned.
|
||||
* @param letter letter of the drive
|
||||
* @return true: drive is ready; false: drive is not ready
|
||||
*/
|
||||
bool lv_fs_is_ready(char letter);
|
||||
|
||||
/**
|
||||
* Open a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
|
||||
* @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mode);
|
||||
|
||||
/**
|
||||
* Close an already opened file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p);
|
||||
|
||||
/**
|
||||
* Delete a file
|
||||
* @param path path of the file to delete
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_remove(const char * path);
|
||||
|
||||
/**
|
||||
* Read from a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param buf pointer to a buffer where the read bytes are stored
|
||||
* @param btr Bytes To Read
|
||||
* @param br the number of real read bytes (Bytes Read). NULL if unused.
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br);
|
||||
|
||||
/**
|
||||
* Write into a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param buf pointer to a buffer with the bytes to write
|
||||
* @param btr Bytes To Write
|
||||
* @param br the number of real written bytes (Bytes Written). NULL if unused.
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw);
|
||||
|
||||
/**
|
||||
* Set the position of the 'cursor' (read write pointer) in a file
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param pos the new position expressed in bytes index (0: start of file)
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos);
|
||||
|
||||
/**
|
||||
* Give the position of the read write pointer
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param pos_p pointer to store the position of the read write pointer
|
||||
* @return LV_FS_RES_OK or any error from 'fs_res_t'
|
||||
*/
|
||||
lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos);
|
||||
|
||||
/**
|
||||
* Truncate the file size to the current position of the read write pointer
|
||||
* @param file_p pointer to an 'ufs_file_t' variable. (opened with lv_fs_open )
|
||||
* @return LV_FS_RES_OK: no error, the file is read
|
||||
* any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_trunc(lv_fs_file_t * file_p);
|
||||
|
||||
/**
|
||||
* Give the size of a file bytes
|
||||
* @param file_p pointer to a lv_fs_file_t variable
|
||||
* @param size pointer to a variable to store the size
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_size(lv_fs_file_t * file_p, uint32_t * size);
|
||||
|
||||
/**
|
||||
* Rename a file
|
||||
* @param oldname path to the file
|
||||
* @param newname path with the new name
|
||||
* @return LV_FS_RES_OK or any error from 'fs_res_t'
|
||||
*/
|
||||
lv_fs_res_t lv_fs_rename(const char * oldname, const char * newname);
|
||||
|
||||
/**
|
||||
* Initialize a 'fs_dir_t' variable for directory reading
|
||||
* @param rddir_p pointer to a 'fs_read_dir_t' variable
|
||||
* @param path path to a directory
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path);
|
||||
|
||||
/**
|
||||
* Read the next filename form a directory.
|
||||
* The name of the directories will begin with '/'
|
||||
* @param rddir_p pointer to an initialized 'fs_rdir_t' variable
|
||||
* @param fn pointer to a buffer to store the filename
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn);
|
||||
|
||||
/**
|
||||
* Close the directory reading
|
||||
* @param rddir_p pointer to an initialized 'fs_dir_t' variable
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p);
|
||||
|
||||
/**
|
||||
* Get the free and total size of a driver in kB
|
||||
* @param letter the driver letter
|
||||
* @param total_p pointer to store the total size [kB]
|
||||
* @param free_p pointer to store the free size [kB]
|
||||
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
|
||||
*/
|
||||
lv_fs_res_t lv_fs_free_space(char letter, uint32_t * total_p, uint32_t * free_p);
|
||||
|
||||
/**
|
||||
* Fill a buffer with the letters of existing drivers
|
||||
* @param buf buffer to store the letters ('\0' added after the last letter)
|
||||
* @return the buffer
|
||||
*/
|
||||
char * lv_fs_get_letters(char * buf);
|
||||
|
||||
/**
|
||||
* Return with the extension of the filename
|
||||
* @param fn string with a filename
|
||||
* @return pointer to the beginning extension or empty string if no extension
|
||||
*/
|
||||
const char * lv_fs_get_ext(const char * fn);
|
||||
|
||||
/**
|
||||
* Step up one level
|
||||
* @param path pointer to a file name
|
||||
* @return the truncated file name
|
||||
*/
|
||||
char * lv_fs_up(char * path);
|
||||
|
||||
/**
|
||||
* Get the last element of a path (e.g. U:/folder/file -> file)
|
||||
* @param buf buffer to store the letters ('\0' added after the last letter)
|
||||
* @return pointer to the beginning of the last element in the path
|
||||
*/
|
||||
const char * lv_fs_get_last(const char * path);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FILESYSTEM*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_FS_H*/
|
||||
40
extended-setup/components/lvgl/src/lv_misc/lv_gc.c
Normal file
40
extended-setup/components/lvgl/src/lv_misc/lv_gc.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file lv_gc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if(!defined(LV_ENABLE_GC)) || LV_ENABLE_GC == 0
|
||||
LV_ROOTS
|
||||
#endif /* LV_ENABLE_GC */
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
74
extended-setup/components/lvgl/src/lv_misc/lv_gc.h
Normal file
74
extended-setup/components/lvgl/src/lv_misc/lv_gc.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @file lv_gc.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GC_H
|
||||
#define LV_GC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lv_mem.h"
|
||||
#include "lv_ll.h"
|
||||
#include "../lv_draw/lv_img_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_GC_ROOTS(prefix) \
|
||||
prefix lv_ll_t _lv_task_ll; /*Linked list to store the lv_tasks*/ \
|
||||
prefix lv_ll_t _lv_disp_ll; /*Linked list of screens*/ \
|
||||
prefix lv_ll_t _lv_indev_ll; /*Linked list of screens*/ \
|
||||
prefix lv_ll_t _lv_drv_ll; \
|
||||
prefix lv_ll_t _lv_file_ll; \
|
||||
prefix lv_ll_t _lv_anim_ll; \
|
||||
prefix lv_ll_t _lv_group_ll; \
|
||||
prefix lv_ll_t _lv_img_defoder_ll; \
|
||||
prefix lv_img_cache_entry_t * _lv_img_cache_array; \
|
||||
prefix void * _lv_task_act; \
|
||||
prefix void * _lv_draw_buf;
|
||||
|
||||
#define LV_NO_PREFIX
|
||||
#define LV_ROOTS LV_GC_ROOTS(LV_NO_PREFIX)
|
||||
|
||||
#if LV_ENABLE_GC == 1
|
||||
#if LV_MEM_CUSTOM != 1
|
||||
#error "GC requires CUSTOM_MEM"
|
||||
#endif /* LV_MEM_CUSTOM */
|
||||
#else /* LV_ENABLE_GC */
|
||||
#define LV_GC_ROOT(x) x
|
||||
LV_GC_ROOTS(extern)
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_GC_H*/
|
||||
430
extended-setup/components/lvgl/src/lv_misc/lv_ll.c
Normal file
430
extended-setup/components/lvgl/src/lv_misc/lv_ll.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/**
|
||||
* @file lv_ll.c
|
||||
* Handle linked lists.
|
||||
* The nodes are dynamically allocated by the 'lv_mem' module,
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lv_ll.h"
|
||||
#include "lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LL_NODE_META_SIZE (sizeof(lv_ll_node_t *) + sizeof(lv_ll_node_t *))
|
||||
#define LL_PREV_P_OFFSET(ll_p) (ll_p->n_size)
|
||||
#define LL_NEXT_P_OFFSET(ll_p) (ll_p->n_size + sizeof(lv_ll_node_t *))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * prev);
|
||||
static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * next);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize linked list
|
||||
* @param ll_dsc pointer to ll_dsc variable
|
||||
* @param node_size the size of 1 node in bytes
|
||||
*/
|
||||
void lv_ll_init(lv_ll_t * ll_p, uint32_t node_size)
|
||||
{
|
||||
ll_p->head = NULL;
|
||||
ll_p->tail = NULL;
|
||||
#ifdef LV_MEM_ENV64
|
||||
/*Round the size up to 8*/
|
||||
if(node_size & 0x7) {
|
||||
node_size = node_size & (~0x7);
|
||||
node_size += 8;
|
||||
}
|
||||
#else
|
||||
/*Round the size up to 4*/
|
||||
if(node_size & 0x3) {
|
||||
node_size = node_size & (~0x3);
|
||||
node_size += 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
ll_p->n_size = node_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new head to a linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the new head
|
||||
*/
|
||||
void * lv_ll_ins_head(lv_ll_t * ll_p)
|
||||
{
|
||||
lv_ll_node_t * n_new;
|
||||
|
||||
n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
|
||||
|
||||
if(n_new != NULL) {
|
||||
node_set_prev(ll_p, n_new, NULL); /*No prev. before the new head*/
|
||||
node_set_next(ll_p, n_new, ll_p->head); /*After new comes the old head*/
|
||||
|
||||
if(ll_p->head != NULL) { /*If there is old head then before it goes the new*/
|
||||
node_set_prev(ll_p, ll_p->head, n_new);
|
||||
}
|
||||
|
||||
ll_p->head = n_new; /*Set the new head in the dsc.*/
|
||||
if(ll_p->tail == NULL) { /*If there is no tail (1. node) set the tail too*/
|
||||
ll_p->tail = n_new;
|
||||
}
|
||||
}
|
||||
|
||||
return n_new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new node in front of the n_act node
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the new head
|
||||
*/
|
||||
void * lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act)
|
||||
{
|
||||
lv_ll_node_t * n_new;
|
||||
lv_ll_node_t * n_prev;
|
||||
|
||||
if(NULL == ll_p || NULL == n_act) return NULL;
|
||||
|
||||
if(lv_ll_get_head(ll_p) == n_act) {
|
||||
n_new = lv_ll_ins_head(ll_p);
|
||||
if(n_new == NULL) return NULL;
|
||||
} else {
|
||||
n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
|
||||
if(n_new == NULL) return NULL;
|
||||
|
||||
n_prev = lv_ll_get_prev(ll_p, n_act);
|
||||
node_set_next(ll_p, n_prev, n_new);
|
||||
node_set_prev(ll_p, n_new, n_prev);
|
||||
node_set_prev(ll_p, n_act, n_new);
|
||||
node_set_next(ll_p, n_new, n_act);
|
||||
}
|
||||
|
||||
return n_new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new tail to a linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the new tail
|
||||
*/
|
||||
void * lv_ll_ins_tail(lv_ll_t * ll_p)
|
||||
{
|
||||
lv_ll_node_t * n_new;
|
||||
|
||||
n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
|
||||
if(n_new == NULL) return NULL;
|
||||
|
||||
if(n_new != NULL) {
|
||||
node_set_next(ll_p, n_new, NULL); /*No next after the new tail*/
|
||||
node_set_prev(ll_p, n_new, ll_p->tail); /*The prev. before new is tho old tail*/
|
||||
if(ll_p->tail != NULL) { /*If there is old tail then the new comes after it*/
|
||||
node_set_next(ll_p, ll_p->tail, n_new);
|
||||
}
|
||||
|
||||
ll_p->tail = n_new; /*Set the new tail in the dsc.*/
|
||||
if(ll_p->head == NULL) { /*If there is no head (1. node) set the head too*/
|
||||
ll_p->head = n_new;
|
||||
}
|
||||
}
|
||||
|
||||
return n_new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the node 'node_p' from 'll_p' linked list.
|
||||
* It does not free the the memory of node.
|
||||
* @param ll_p pointer to the linked list of 'node_p'
|
||||
* @param node_p pointer to node in 'll_p' linked list
|
||||
*/
|
||||
void lv_ll_rem(lv_ll_t * ll_p, void * node_p)
|
||||
{
|
||||
if(lv_ll_get_head(ll_p) == node_p) {
|
||||
/*The new head will be the node after 'n_act'*/
|
||||
ll_p->head = lv_ll_get_next(ll_p, node_p);
|
||||
if(ll_p->head == NULL) {
|
||||
ll_p->tail = NULL;
|
||||
} else {
|
||||
node_set_prev(ll_p, ll_p->head, NULL);
|
||||
}
|
||||
} else if(lv_ll_get_tail(ll_p) == node_p) {
|
||||
/*The new tail will be the node before 'n_act'*/
|
||||
ll_p->tail = lv_ll_get_prev(ll_p, node_p);
|
||||
if(ll_p->tail == NULL) {
|
||||
ll_p->head = NULL;
|
||||
} else {
|
||||
node_set_next(ll_p, ll_p->tail, NULL);
|
||||
}
|
||||
} else {
|
||||
lv_ll_node_t * n_prev = lv_ll_get_prev(ll_p, node_p);
|
||||
lv_ll_node_t * n_next = lv_ll_get_next(ll_p, node_p);
|
||||
|
||||
node_set_next(ll_p, n_prev, n_next);
|
||||
node_set_prev(ll_p, n_next, n_prev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove and free all elements from a linked list. The list remain valid but become empty.
|
||||
* @param ll_p pointer to linked list
|
||||
*/
|
||||
void lv_ll_clear(lv_ll_t * ll_p)
|
||||
{
|
||||
void * i;
|
||||
void * i_next;
|
||||
|
||||
i = lv_ll_get_head(ll_p);
|
||||
i_next = NULL;
|
||||
|
||||
while(i != NULL) {
|
||||
i_next = lv_ll_get_next(ll_p, i);
|
||||
|
||||
lv_ll_rem(ll_p, i);
|
||||
lv_mem_free(i);
|
||||
|
||||
i = i_next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a node to a new linked list
|
||||
* @param ll_ori_p pointer to the original (old) linked list
|
||||
* @param ll_new_p pointer to the new linked list
|
||||
* @param node pointer to a node
|
||||
* @param head true: be the head in the new list
|
||||
* false be the head in the new list
|
||||
*/
|
||||
void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head)
|
||||
{
|
||||
lv_ll_rem(ll_ori_p, node);
|
||||
|
||||
if(head) {
|
||||
/*Set node as head*/
|
||||
node_set_prev(ll_new_p, node, NULL);
|
||||
node_set_next(ll_new_p, node, ll_new_p->head);
|
||||
|
||||
if(ll_new_p->head != NULL) { /*If there is old head then before it goes the new*/
|
||||
node_set_prev(ll_new_p, ll_new_p->head, node);
|
||||
}
|
||||
|
||||
ll_new_p->head = node; /*Set the new head in the dsc.*/
|
||||
if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/
|
||||
ll_new_p->tail = node;
|
||||
}
|
||||
} else {
|
||||
/*Set node as tail*/
|
||||
node_set_prev(ll_new_p, node, ll_new_p->tail);
|
||||
node_set_next(ll_new_p, node, NULL);
|
||||
|
||||
if(ll_new_p->tail != NULL) { /*If there is old tail then after it goes the new*/
|
||||
node_set_next(ll_new_p, ll_new_p->tail, node);
|
||||
}
|
||||
|
||||
ll_new_p->tail = node; /*Set the new tail in the dsc.*/
|
||||
if(ll_new_p->head == NULL) { /*If there is no head (first node) set the head too*/
|
||||
ll_new_p->head = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with head node of the linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the head of 'll_p'
|
||||
*/
|
||||
void * lv_ll_get_head(const lv_ll_t * ll_p)
|
||||
{
|
||||
void * head = NULL;
|
||||
|
||||
if(ll_p != NULL) {
|
||||
head = ll_p->head;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with tail node of the linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the head of 'll_p'
|
||||
*/
|
||||
void * lv_ll_get_tail(const lv_ll_t * ll_p)
|
||||
{
|
||||
void * tail = NULL;
|
||||
|
||||
if(ll_p != NULL) {
|
||||
tail = ll_p->tail;
|
||||
}
|
||||
|
||||
return tail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the pointer of the next node after 'n_act'
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the next node
|
||||
*/
|
||||
void * lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act)
|
||||
{
|
||||
void * next = NULL;
|
||||
|
||||
if(ll_p != NULL) {
|
||||
const lv_ll_node_t * n_act_d = n_act;
|
||||
memcpy(&next, n_act_d + LL_NEXT_P_OFFSET(ll_p), sizeof(void *));
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the pointer of the previous node after 'n_act'
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the previous node
|
||||
*/
|
||||
void * lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act)
|
||||
{
|
||||
void * prev = NULL;
|
||||
|
||||
if(ll_p != NULL) {
|
||||
const lv_ll_node_t * n_act_d = n_act;
|
||||
memcpy(&prev, n_act_d + LL_PREV_P_OFFSET(ll_p), sizeof(void *));
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the linked list.
|
||||
* @param ll_p pointer to linked list
|
||||
* @return length of the linked list
|
||||
*/
|
||||
uint32_t lv_ll_get_len(const lv_ll_t * ll_p)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
void * node;
|
||||
|
||||
for(node = lv_ll_get_head(ll_p); node != NULL; node = lv_ll_get_next(ll_p, node)) {
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void lv_ll_swap(lv_ll_t * ll_p, void * n1_p, void * n2_p)
|
||||
{
|
||||
(void)(ll_p);
|
||||
(void)(n1_p);
|
||||
(void)(n2_p);
|
||||
/*TODO*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a nodw before an other node in the same linked list
|
||||
* @param ll_p pointer to a linked list
|
||||
* @param n_act pointer to node to move
|
||||
* @param n_after pointer to a node which should be after `n_act`
|
||||
*/
|
||||
void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after)
|
||||
{
|
||||
if(n_act == n_after) return; /*Can't move before itself*/
|
||||
|
||||
void * n_before;
|
||||
if(n_after != NULL)
|
||||
n_before = lv_ll_get_prev(ll_p, n_after);
|
||||
else
|
||||
n_before = lv_ll_get_tail(ll_p); /*if `n_after` is NULL `n_act` should be the new tail*/
|
||||
|
||||
if(n_act == n_before) return; /*Already before `n_after`*/
|
||||
|
||||
/*It's much easier to remove from the list and add again*/
|
||||
lv_ll_rem(ll_p, n_act);
|
||||
|
||||
/*Add again by setting the prev. and next nodes*/
|
||||
node_set_next(ll_p, n_before, n_act);
|
||||
node_set_prev(ll_p, n_act, n_before);
|
||||
node_set_prev(ll_p, n_after, n_act);
|
||||
node_set_next(ll_p, n_act, n_after);
|
||||
|
||||
/*If `n_act` was moved before NULL then it become the new tail*/
|
||||
if(n_after == NULL) ll_p->tail = n_act;
|
||||
|
||||
/*If `n_act` was moved before `NULL` then it's the new head*/
|
||||
if(n_before == NULL) ll_p->head = n_act;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a linked list is empty
|
||||
* @param ll_p pointer to a linked list
|
||||
* @return true: the linked list is empty; false: not empty
|
||||
*/
|
||||
bool lv_ll_is_empty(lv_ll_t * ll_p)
|
||||
{
|
||||
if(ll_p == NULL) return true;
|
||||
|
||||
if(ll_p->head == NULL && ll_p->tail == NULL) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Set the 'pervious node pointer' of a node
|
||||
* @param ll_p pointer to linked list
|
||||
* @param act pointer to a node which prev. node pointer should be set
|
||||
* @param prev pointer to a node which should be the previous node before 'act'
|
||||
*/
|
||||
static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * prev)
|
||||
{
|
||||
if(act == NULL) return; /*Can't set the prev node of `NULL`*/
|
||||
|
||||
uint32_t node_p_size = sizeof(lv_ll_node_t *);
|
||||
if(prev)
|
||||
memcpy(act + LL_PREV_P_OFFSET(ll_p), &prev, node_p_size);
|
||||
else
|
||||
memset(act + LL_PREV_P_OFFSET(ll_p), 0, node_p_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'next node pointer' of a node
|
||||
* @param ll_p pointer to linked list
|
||||
* @param act pointer to a node which next node pointer should be set
|
||||
* @param next pointer to a node which should be the next node before 'act'
|
||||
*/
|
||||
static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * next)
|
||||
{
|
||||
if(act == NULL) return; /*Can't set the next node of `NULL`*/
|
||||
|
||||
uint32_t node_p_size = sizeof(lv_ll_node_t *);
|
||||
if(next)
|
||||
memcpy(act + LL_NEXT_P_OFFSET(ll_p), &next, node_p_size);
|
||||
else
|
||||
memset(act + LL_NEXT_P_OFFSET(ll_p), 0, node_p_size);
|
||||
}
|
||||
160
extended-setup/components/lvgl/src/lv_misc/lv_ll.h
Normal file
160
extended-setup/components/lvgl/src/lv_misc/lv_ll.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* @file lv_ll.c
|
||||
* Handle linked lists. The nodes are dynamically allocated by the 'lv_mem' module.
|
||||
*/
|
||||
|
||||
#ifndef LV_LL_H
|
||||
#define LV_LL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_mem.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Dummy type to make handling easier*/
|
||||
typedef uint8_t lv_ll_node_t;
|
||||
|
||||
/** Description of a linked list*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t n_size;
|
||||
lv_ll_node_t * head;
|
||||
lv_ll_node_t * tail;
|
||||
} lv_ll_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize linked list
|
||||
* @param ll_dsc pointer to ll_dsc variable
|
||||
* @param node_size the size of 1 node in bytes
|
||||
*/
|
||||
void lv_ll_init(lv_ll_t * ll_p, uint32_t node_size);
|
||||
|
||||
/**
|
||||
* Add a new head to a linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the new head
|
||||
*/
|
||||
void * lv_ll_ins_head(lv_ll_t * ll_p);
|
||||
|
||||
/**
|
||||
* Insert a new node in front of the n_act node
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the new head
|
||||
*/
|
||||
void * lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act);
|
||||
|
||||
/**
|
||||
* Add a new tail to a linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the new tail
|
||||
*/
|
||||
void * lv_ll_ins_tail(lv_ll_t * ll_p);
|
||||
|
||||
/**
|
||||
* Remove the node 'node_p' from 'll_p' linked list.
|
||||
* It does not free the the memory of node.
|
||||
* @param ll_p pointer to the linked list of 'node_p'
|
||||
* @param node_p pointer to node in 'll_p' linked list
|
||||
*/
|
||||
void lv_ll_rem(lv_ll_t * ll_p, void * node_p);
|
||||
|
||||
/**
|
||||
* Remove and free all elements from a linked list. The list remain valid but become empty.
|
||||
* @param ll_p pointer to linked list
|
||||
*/
|
||||
void lv_ll_clear(lv_ll_t * ll_p);
|
||||
|
||||
/**
|
||||
* Move a node to a new linked list
|
||||
* @param ll_ori_p pointer to the original (old) linked list
|
||||
* @param ll_new_p pointer to the new linked list
|
||||
* @param node pointer to a node
|
||||
* @param head true: be the head in the new list
|
||||
* false be the head in the new list
|
||||
*/
|
||||
void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head);
|
||||
|
||||
/**
|
||||
* Return with head node of the linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the head of 'll_p'
|
||||
*/
|
||||
void * lv_ll_get_head(const lv_ll_t * ll_p);
|
||||
|
||||
/**
|
||||
* Return with tail node of the linked list
|
||||
* @param ll_p pointer to linked list
|
||||
* @return pointer to the head of 'll_p'
|
||||
*/
|
||||
void * lv_ll_get_tail(const lv_ll_t * ll_p);
|
||||
|
||||
/**
|
||||
* Return with the pointer of the next node after 'n_act'
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the next node
|
||||
*/
|
||||
void * lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act);
|
||||
|
||||
/**
|
||||
* Return with the pointer of the previous node after 'n_act'
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the previous node
|
||||
*/
|
||||
void * lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act);
|
||||
|
||||
/**
|
||||
* Return the length of the linked list.
|
||||
* @param ll_p pointer to linked list
|
||||
* @return length of the linked list
|
||||
*/
|
||||
uint32_t lv_ll_get_len(const lv_ll_t * ll_p);
|
||||
|
||||
/**
|
||||
* Move a nodw before an other node in the same linked list
|
||||
* @param ll_p pointer to a linked list
|
||||
* @param n_act pointer to node to move
|
||||
* @param n_after pointer to a node which should be after `n_act`
|
||||
*/
|
||||
void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after);
|
||||
|
||||
/**
|
||||
* Check if a linked list is empty
|
||||
* @param ll_p pointer to a linked list
|
||||
* @return true: the linked list is empty; false: not empty
|
||||
*/
|
||||
bool lv_ll_is_empty(lv_ll_t * ll_p);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define LV_LL_READ(list, i) for(i = lv_ll_get_head(&list); i != NULL; i = lv_ll_get_next(&list, i))
|
||||
|
||||
#define LV_LL_READ_BACK(list, i) for(i = lv_ll_get_tail(&list); i != NULL; i = lv_ll_get_prev(&list, i))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
77
extended-setup/components/lvgl/src/lv_misc/lv_log.c
Normal file
77
extended-setup/components/lvgl/src/lv_misc/lv_log.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file lv_log.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_log.h"
|
||||
#if LV_USE_LOG
|
||||
|
||||
#if LV_LOG_PRINTF
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_log_print_g_cb_t custom_print_cb;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Register custom print/write function to call when a log is added.
|
||||
* It can format its "File path", "Line number" and "Description" as required
|
||||
* and send the formatted log message to a consol or serial port.
|
||||
* @param print_cb a function pointer to print a log
|
||||
*/
|
||||
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb)
|
||||
{
|
||||
custom_print_cb = print_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a log
|
||||
* @param level the level of log. (From `lv_log_level_t` enum)
|
||||
* @param file name of the file when the log added
|
||||
* @param line line number in the source code where the log added
|
||||
* @param dsc description of the log
|
||||
*/
|
||||
void lv_log_add(lv_log_level_t level, const char * file, int line, const char * dsc)
|
||||
{
|
||||
if(level >= _LV_LOG_LEVEL_NUM) return; /*Invalid level*/
|
||||
|
||||
if(level >= LV_LOG_LEVEL) {
|
||||
|
||||
#if LV_LOG_PRINTF
|
||||
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
|
||||
printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], dsc, file, line);
|
||||
#else
|
||||
if(custom_print_cb) custom_print_cb(level, file, line, dsc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_LOG*/
|
||||
138
extended-setup/components/lvgl/src/lv_misc/lv_log.h
Normal file
138
extended-setup/components/lvgl/src/lv_misc/lv_log.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file lv_log.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LOG_H
|
||||
#define LV_LOG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/*Possible log level. For compatibility declare it independently from `LV_USE_LOG`*/
|
||||
|
||||
#define LV_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information*/
|
||||
#define LV_LOG_LEVEL_INFO 1 /**< Log important events*/
|
||||
#define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/
|
||||
#define LV_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail*/
|
||||
#define LV_LOG_LEVEL_NONE 4 /**< Do not log anything*/
|
||||
#define _LV_LOG_LEVEL_NUM 5 /**< Number of log levels */
|
||||
|
||||
typedef int8_t lv_log_level_t;
|
||||
|
||||
#if LV_USE_LOG
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Log print function. Receives "Log Level", "File path", "Line number" and "Description".
|
||||
*/
|
||||
typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t, const char *);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Register custom print/write function to call when a log is added.
|
||||
* It can format its "File path", "Line number" and "Description" as required
|
||||
* and send the formatted log message to a consol or serial port.
|
||||
* @param print_cb a function pointer to print a log
|
||||
*/
|
||||
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb);
|
||||
|
||||
/**
|
||||
* Add a log
|
||||
* @param level the level of log. (From `lv_log_level_t` enum)
|
||||
* @param file name of the file when the log added
|
||||
* @param line line number in the source code where the log added
|
||||
* @param dsc description of the log
|
||||
*/
|
||||
void lv_log_add(lv_log_level_t level, const char * file, int line, const char * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE
|
||||
#define LV_LOG_TRACE(dsc) lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, dsc);
|
||||
#else
|
||||
#define LV_LOG_TRACE(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
|
||||
#define LV_LOG_INFO(dsc) lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, dsc);
|
||||
#else
|
||||
#define LV_LOG_INFO(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN
|
||||
#define LV_LOG_WARN(dsc) lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, dsc);
|
||||
#else
|
||||
#define LV_LOG_WARN(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR
|
||||
#define LV_LOG_ERROR(dsc) lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, dsc);
|
||||
#else
|
||||
#define LV_LOG_ERROR(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /*LV_USE_LOG*/
|
||||
|
||||
/*Do nothing if `LV_USE_LOG 0`*/
|
||||
#define lv_log_add(level, file, line, dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#define LV_LOG_TRACE(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#define LV_LOG_INFO(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#define LV_LOG_WARN(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#define LV_LOG_ERROR(dsc) \
|
||||
{ \
|
||||
; \
|
||||
}
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LOG_H*/
|
||||
99
extended-setup/components/lvgl/src/lv_misc/lv_math.c
Normal file
99
extended-setup/components/lvgl/src/lv_misc/lv_math.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file lv_math.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_math.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static int16_t sin0_90_table[] = {
|
||||
0, 572, 1144, 1715, 2286, 2856, 3425, 3993, 4560, 5126, 5690, 6252, 6813, 7371, 7927, 8481,
|
||||
9032, 9580, 10126, 10668, 11207, 11743, 12275, 12803, 13328, 13848, 14364, 14876, 15383, 15886, 16383, 16876,
|
||||
17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964,
|
||||
24351, 24730, 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 28377, 28659, 28932, 29196,
|
||||
29451, 29697, 29934, 30162, 30381, 30591, 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165,
|
||||
32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return with sinus of an angle
|
||||
* @param angle
|
||||
* @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767
|
||||
*/
|
||||
int16_t lv_trigo_sin(int16_t angle)
|
||||
{
|
||||
int16_t ret = 0;
|
||||
angle = angle % 360;
|
||||
|
||||
if(angle < 0) angle = 360 + angle;
|
||||
|
||||
if(angle < 90) {
|
||||
ret = sin0_90_table[angle];
|
||||
} else if(angle >= 90 && angle < 180) {
|
||||
angle = 180 - angle;
|
||||
ret = sin0_90_table[angle];
|
||||
} else if(angle >= 180 && angle < 270) {
|
||||
angle = angle - 180;
|
||||
ret = -sin0_90_table[angle];
|
||||
} else { /*angle >=270*/
|
||||
angle = 360 - angle;
|
||||
ret = -sin0_90_table[angle];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a value of a Cubic Bezier function.
|
||||
* @param t time in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u0 start values in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u3 end values in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX]
|
||||
*/
|
||||
int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
|
||||
{
|
||||
uint32_t t_rem = 1024 - t;
|
||||
uint32_t t_rem2 = (t_rem * t_rem) >> 10;
|
||||
uint32_t t_rem3 = (t_rem2 * t_rem) >> 10;
|
||||
uint32_t t2 = (t * t) >> 10;
|
||||
uint32_t t3 = (t2 * t) >> 10;
|
||||
|
||||
uint32_t v1 = ((uint32_t)t_rem3 * u0) >> 10;
|
||||
uint32_t v2 = ((uint32_t)3 * t_rem2 * t * u1) >> 20;
|
||||
uint32_t v3 = ((uint32_t)3 * t_rem * t2 * u2) >> 20;
|
||||
uint32_t v4 = ((uint32_t)t3 * u3) >> 10;
|
||||
|
||||
return v1 + v2 + v3 + v4;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
65
extended-setup/components/lvgl/src/lv_misc/lv_math.h
Normal file
65
extended-setup/components/lvgl/src/lv_misc/lv_math.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file math_base.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MATH_H
|
||||
#define LV_MATH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_MATH_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define LV_MATH_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define LV_MATH_ABS(x) ((x) > 0 ? (x) : (-(x)))
|
||||
|
||||
#define LV_TRIGO_SIN_MAX 32767
|
||||
#define LV_TRIGO_SHIFT 15 /**< >> LV_TRIGO_SHIFT to normalize*/
|
||||
|
||||
#define LV_BEZIER_VAL_MAX 1024 /**< Max time in Bezier functions (not [0..1] to use integers) */
|
||||
#define LV_BEZIER_VAL_SHIFT 10 /**< log2(LV_BEZIER_VAL_MAX): used to normalize up scaled values*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return with sinus of an angle
|
||||
* @param angle
|
||||
* @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767
|
||||
*/
|
||||
int16_t lv_trigo_sin(int16_t angle);
|
||||
|
||||
/**
|
||||
* Calculate a value of a Cubic Bezier function.
|
||||
* @param t time in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u0 start values in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @param u3 end values in range of [0..LV_BEZIER_VAL_MAX]
|
||||
* @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX]
|
||||
*/
|
||||
int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
464
extended-setup/components/lvgl/src/lv_misc/lv_mem.c
Normal file
464
extended-setup/components/lvgl/src/lv_misc/lv_mem.c
Normal file
@@ -0,0 +1,464 @@
|
||||
/**
|
||||
* @file lv_mem.c
|
||||
* General and portable implementation of malloc and free.
|
||||
* The dynamic memory monitoring is also supported.
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_mem.h"
|
||||
#include "lv_math.h"
|
||||
#include <string.h>
|
||||
|
||||
#if LV_MEM_CUSTOM != 0
|
||||
#include LV_MEM_CUSTOM_INCLUDE
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Add memory junk on alloc (0xaa) and free(0xbb) (just for testing purposes)*/
|
||||
#define LV_MEM_ADD_JUNK 1
|
||||
|
||||
#ifdef LV_MEM_ENV64
|
||||
#define MEM_UNIT uint64_t
|
||||
#else
|
||||
#define MEM_UNIT uint32_t
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#if LV_ENABLE_GC == 0 /*gc custom allocations must not include header*/
|
||||
|
||||
/*The size of this union must be 4 bytes (uint32_t)*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
MEM_UNIT used : 1; // 1: if the entry is used
|
||||
MEM_UNIT d_size : 31; // Size off the data (1 means 4 bytes)
|
||||
} s;
|
||||
MEM_UNIT header; // The header (used + d_size)
|
||||
} lv_mem_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lv_mem_header_t header;
|
||||
uint8_t first_data; /*First data byte in the allocated data (Just for easily create a pointer)*/
|
||||
} lv_mem_ent_t;
|
||||
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e);
|
||||
static void * ent_alloc(lv_mem_ent_t * e, uint32_t size);
|
||||
static void ent_trunc(lv_mem_ent_t * e, uint32_t size);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
static uint8_t * work_mem;
|
||||
#endif
|
||||
|
||||
static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initiaiize the dyn_mem module (work memory and other variables)
|
||||
*/
|
||||
void lv_mem_init(void)
|
||||
{
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
|
||||
#if LV_MEM_ADR == 0
|
||||
/*Allocate a large array to store the dynamically allocated data*/
|
||||
static LV_MEM_ATTR MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)];
|
||||
work_mem = (uint8_t *)work_mem_int;
|
||||
#else
|
||||
work_mem = (uint8_t *)LV_MEM_ADR;
|
||||
#endif
|
||||
|
||||
lv_mem_ent_t * full = (lv_mem_ent_t *)work_mem;
|
||||
full->header.s.used = 0;
|
||||
/*The total mem size id reduced by the first header and the close patterns */
|
||||
full->header.s.d_size = LV_MEM_SIZE - sizeof(lv_mem_header_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a memory dynamically
|
||||
* @param size size of the memory to allocate in bytes
|
||||
* @return pointer to the allocated memory
|
||||
*/
|
||||
void * lv_mem_alloc(uint32_t size)
|
||||
{
|
||||
if(size == 0) {
|
||||
return &zero_mem;
|
||||
}
|
||||
|
||||
#ifdef LV_MEM_ENV64
|
||||
/*Round the size up to 8*/
|
||||
if(size & 0x7) {
|
||||
size = size & (~0x7);
|
||||
size += 8;
|
||||
}
|
||||
#else
|
||||
/*Round the size up to 4*/
|
||||
if(size & 0x3) {
|
||||
size = size & (~0x3);
|
||||
size += 4;
|
||||
}
|
||||
#endif
|
||||
void * alloc = NULL;
|
||||
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/*Use the built-in allocators*/
|
||||
lv_mem_ent_t * e = NULL;
|
||||
|
||||
// Search for a appropriate entry
|
||||
do {
|
||||
// Get the next entry
|
||||
e = ent_get_next(e);
|
||||
|
||||
/*If there is next entry then try to allocate there*/
|
||||
if(e != NULL) {
|
||||
alloc = ent_alloc(e, size);
|
||||
}
|
||||
// End if there is not next entry OR the alloc. is successful
|
||||
} while(e != NULL && alloc == NULL);
|
||||
|
||||
#else
|
||||
/*Use custom, user defined malloc function*/
|
||||
#if LV_ENABLE_GC == 1 /*gc must not include header*/
|
||||
alloc = LV_MEM_CUSTOM_ALLOC(size);
|
||||
#else /* LV_ENABLE_GC */
|
||||
/*Allocate a header too to store the size*/
|
||||
alloc = LV_MEM_CUSTOM_ALLOC(size + sizeof(lv_mem_header_t));
|
||||
if(alloc != NULL) {
|
||||
((lv_mem_ent_t *)alloc)->header.s.d_size = size;
|
||||
((lv_mem_ent_t *)alloc)->header.s.used = 1;
|
||||
|
||||
alloc = &((lv_mem_ent_t *)alloc)->first_data;
|
||||
}
|
||||
#endif /* LV_ENABLE_GC */
|
||||
#endif /* LV_MEM_CUSTOM */
|
||||
|
||||
#if LV_MEM_ADD_JUNK
|
||||
if(alloc != NULL) memset(alloc, 0xaa, size);
|
||||
#endif
|
||||
|
||||
if(alloc == NULL) LV_LOG_WARN("Couldn't allocate memory");
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an allocated data
|
||||
* @param data pointer to an allocated memory
|
||||
*/
|
||||
void lv_mem_free(const void * data)
|
||||
{
|
||||
if(data == &zero_mem) return;
|
||||
if(data == NULL) return;
|
||||
|
||||
#if LV_MEM_ADD_JUNK
|
||||
memset((void *)data, 0xbb, lv_mem_get_size(data));
|
||||
#endif
|
||||
|
||||
#if LV_ENABLE_GC == 0
|
||||
/*e points to the header*/
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *)data - sizeof(lv_mem_header_t));
|
||||
e->header.s.used = 0;
|
||||
#endif
|
||||
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
#if LV_MEM_AUTO_DEFRAG
|
||||
/* Make a simple defrag.
|
||||
* Join the following free entries after this*/
|
||||
lv_mem_ent_t * e_next;
|
||||
e_next = ent_get_next(e);
|
||||
while(e_next != NULL) {
|
||||
if(e_next->header.s.used == 0) {
|
||||
e->header.s.d_size += e_next->header.s.d_size + sizeof(e->header);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
e_next = ent_get_next(e_next);
|
||||
}
|
||||
#endif
|
||||
#else /*Use custom, user defined free function*/
|
||||
#if LV_ENABLE_GC == 0
|
||||
LV_MEM_CUSTOM_FREE(e);
|
||||
#else
|
||||
LV_MEM_CUSTOM_FREE((void *)data);
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocate a memory with a new size. The old content will be kept.
|
||||
* @param data pointer to an allocated memory.
|
||||
* Its content will be copied to the new memory block and freed
|
||||
* @param new_size the desired new size in byte
|
||||
* @return pointer to the new memory
|
||||
*/
|
||||
|
||||
#if LV_ENABLE_GC == 0
|
||||
|
||||
void * lv_mem_realloc(void * data_p, uint32_t new_size)
|
||||
{
|
||||
/*data_p could be previously freed pointer (in this case it is invalid)*/
|
||||
if(data_p != NULL) {
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *)data_p - sizeof(lv_mem_header_t));
|
||||
if(e->header.s.used == 0) {
|
||||
data_p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t old_size = lv_mem_get_size(data_p);
|
||||
if(old_size == new_size) return data_p; /*Also avoid reallocating the same memory*/
|
||||
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/* Truncate the memory if the new size is smaller. */
|
||||
if(new_size < old_size) {
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *)data_p - sizeof(lv_mem_header_t));
|
||||
ent_trunc(e, new_size);
|
||||
return &e->first_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
void * new_p;
|
||||
new_p = lv_mem_alloc(new_size);
|
||||
|
||||
if(new_p != NULL && data_p != NULL) {
|
||||
/*Copy the old data to the new. Use the smaller size*/
|
||||
if(old_size != 0) {
|
||||
memcpy(new_p, data_p, LV_MATH_MIN(new_size, old_size));
|
||||
lv_mem_free(data_p);
|
||||
}
|
||||
}
|
||||
|
||||
if(new_p == NULL) LV_LOG_WARN("Couldn't allocate memory");
|
||||
|
||||
return new_p;
|
||||
}
|
||||
|
||||
#else /* LV_ENABLE_GC */
|
||||
|
||||
void * lv_mem_realloc(void * data_p, uint32_t new_size)
|
||||
{
|
||||
void * new_p = LV_MEM_CUSTOM_REALLOC(data_p, new_size);
|
||||
if(new_p == NULL) LV_LOG_WARN("Couldn't allocate memory");
|
||||
return new_p;
|
||||
}
|
||||
|
||||
#endif /* lv_enable_gc */
|
||||
|
||||
/**
|
||||
* Join the adjacent free memory blocks
|
||||
*/
|
||||
void lv_mem_defrag(void)
|
||||
{
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
lv_mem_ent_t * e_free;
|
||||
lv_mem_ent_t * e_next;
|
||||
e_free = ent_get_next(NULL);
|
||||
|
||||
while(1) {
|
||||
/*Search the next free entry*/
|
||||
while(e_free != NULL) {
|
||||
if(e_free->header.s.used != 0) {
|
||||
e_free = ent_get_next(e_free);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(e_free == NULL) return;
|
||||
|
||||
/*Joint the following free entries to the free*/
|
||||
e_next = ent_get_next(e_free);
|
||||
while(e_next != NULL) {
|
||||
if(e_next->header.s.used == 0) {
|
||||
e_free->header.s.d_size += e_next->header.s.d_size + sizeof(e_next->header);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
e_next = ent_get_next(e_next);
|
||||
}
|
||||
|
||||
if(e_next == NULL) return;
|
||||
|
||||
/*Continue from the lastly checked entry*/
|
||||
e_free = e_next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Give information about the work memory of dynamic allocation
|
||||
* @param mon_p pointer to a dm_mon_p variable,
|
||||
* the result of the analysis will be stored here
|
||||
*/
|
||||
void lv_mem_monitor(lv_mem_monitor_t * mon_p)
|
||||
{
|
||||
/*Init the data*/
|
||||
memset(mon_p, 0, sizeof(lv_mem_monitor_t));
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
lv_mem_ent_t * e;
|
||||
e = NULL;
|
||||
|
||||
e = ent_get_next(e);
|
||||
|
||||
while(e != NULL) {
|
||||
if(e->header.s.used == 0) {
|
||||
mon_p->free_cnt++;
|
||||
mon_p->free_size += e->header.s.d_size;
|
||||
if(e->header.s.d_size > mon_p->free_biggest_size) {
|
||||
mon_p->free_biggest_size = e->header.s.d_size;
|
||||
}
|
||||
} else {
|
||||
mon_p->used_cnt++;
|
||||
}
|
||||
|
||||
e = ent_get_next(e);
|
||||
}
|
||||
mon_p->total_size = LV_MEM_SIZE;
|
||||
mon_p->used_pct = 100 - (100U * mon_p->free_size) / mon_p->total_size;
|
||||
mon_p->frag_pct = (uint32_t)mon_p->free_biggest_size * 100U / mon_p->free_size;
|
||||
mon_p->frag_pct = 100 - mon_p->frag_pct;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the size of an allocated memory
|
||||
* @param data pointer to an allocated memory
|
||||
* @return the size of data memory in bytes
|
||||
*/
|
||||
|
||||
#if LV_ENABLE_GC == 0
|
||||
|
||||
uint32_t lv_mem_get_size(const void * data)
|
||||
{
|
||||
if(data == NULL) return 0;
|
||||
if(data == &zero_mem) return 0;
|
||||
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *)data - sizeof(lv_mem_header_t));
|
||||
|
||||
return e->header.s.d_size;
|
||||
}
|
||||
|
||||
#else /* LV_ENABLE_GC */
|
||||
|
||||
uint32_t lv_mem_get_size(const void * data)
|
||||
{
|
||||
return LV_MEM_CUSTOM_GET_SIZE(data);
|
||||
}
|
||||
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/**
|
||||
* Give the next entry after 'act_e'
|
||||
* @param act_e pointer to an entry
|
||||
* @return pointer to an entry after 'act_e'
|
||||
*/
|
||||
static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e)
|
||||
{
|
||||
lv_mem_ent_t * next_e = NULL;
|
||||
|
||||
if(act_e == NULL) { /*NULL means: get the first entry*/
|
||||
next_e = (lv_mem_ent_t *)work_mem;
|
||||
} else { /*Get the next entry */
|
||||
uint8_t * data = &act_e->first_data;
|
||||
next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size];
|
||||
|
||||
if(&next_e->first_data >= &work_mem[LV_MEM_SIZE]) next_e = NULL;
|
||||
}
|
||||
|
||||
return next_e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to do the real allocation with a given size
|
||||
* @param e try to allocate to this entry
|
||||
* @param size size of the new memory in bytes
|
||||
* @return pointer to the allocated memory or NULL if not enough memory in the entry
|
||||
*/
|
||||
static void * ent_alloc(lv_mem_ent_t * e, uint32_t size)
|
||||
{
|
||||
void * alloc = NULL;
|
||||
|
||||
/*If the memory is free and big enough then use it */
|
||||
if(e->header.s.used == 0 && e->header.s.d_size >= size) {
|
||||
/*Truncate the entry to the desired size */
|
||||
ent_trunc(e, size),
|
||||
|
||||
e->header.s.used = 1;
|
||||
|
||||
/*Save the allocated data*/
|
||||
alloc = &e->first_data;
|
||||
}
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate the data of entry to the given size
|
||||
* @param e Pointer to an entry
|
||||
* @param size new size in bytes
|
||||
*/
|
||||
static void ent_trunc(lv_mem_ent_t * e, uint32_t size)
|
||||
{
|
||||
#ifdef LV_MEM_ENV64
|
||||
/*Round the size up to 8*/
|
||||
if(size & 0x7) {
|
||||
size = size & (~0x7);
|
||||
size += 8;
|
||||
}
|
||||
#else
|
||||
/*Round the size up to 4*/
|
||||
if(size & 0x3) {
|
||||
size = size & (~0x3);
|
||||
size += 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Don't let empty space only for a header without data*/
|
||||
if(e->header.s.d_size == size + sizeof(lv_mem_header_t)) {
|
||||
size = e->header.s.d_size;
|
||||
}
|
||||
|
||||
/* Create the new entry after the current if there is space for it */
|
||||
if(e->header.s.d_size != size) {
|
||||
uint8_t * e_data = &e->first_data;
|
||||
lv_mem_ent_t * after_new_e = (lv_mem_ent_t *)&e_data[size];
|
||||
after_new_e->header.s.used = 0;
|
||||
after_new_e->header.s.d_size = e->header.s.d_size - size - sizeof(lv_mem_header_t);
|
||||
}
|
||||
|
||||
/* Set the new size for the original entry */
|
||||
e->header.s.d_size = size;
|
||||
}
|
||||
|
||||
#endif
|
||||
138
extended-setup/components/lvgl/src/lv_misc/lv_mem.h
Normal file
138
extended-setup/components/lvgl/src/lv_misc/lv_mem.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file lv_mem.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MEM_H
|
||||
#define LV_MEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
// Check windows
|
||||
#ifdef __WIN64
|
||||
#define LV_MEM_ENV64
|
||||
#endif
|
||||
|
||||
// Check GCC
|
||||
#ifdef __GNUC__
|
||||
#if defined(__x86_64__) || defined(__ppc64__)
|
||||
#define LV_MEM_ENV64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Heap information structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total_size; /**< Total heap size */
|
||||
uint32_t free_cnt;
|
||||
uint32_t free_size; /**< Size of available memory */
|
||||
uint32_t free_biggest_size;
|
||||
uint32_t used_cnt;
|
||||
uint8_t used_pct; /**< Percentage used */
|
||||
uint8_t frag_pct; /**< Amount of fragmentation */
|
||||
} lv_mem_monitor_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initiaize the dyn_mem module (work memory and other variables)
|
||||
*/
|
||||
void lv_mem_init(void);
|
||||
|
||||
/**
|
||||
* Allocate a memory dynamically
|
||||
* @param size size of the memory to allocate in bytes
|
||||
* @return pointer to the allocated memory
|
||||
*/
|
||||
void * lv_mem_alloc(uint32_t size);
|
||||
|
||||
/**
|
||||
* Free an allocated data
|
||||
* @param data pointer to an allocated memory
|
||||
*/
|
||||
void lv_mem_free(const void * data);
|
||||
|
||||
/**
|
||||
* Reallocate a memory with a new size. The old content will be kept.
|
||||
* @param data pointer to an allocated memory.
|
||||
* Its content will be copied to the new memory block and freed
|
||||
* @param new_size the desired new size in byte
|
||||
* @return pointer to the new memory
|
||||
*/
|
||||
void * lv_mem_realloc(void * data_p, uint32_t new_size);
|
||||
|
||||
/**
|
||||
* Join the adjacent free memory blocks
|
||||
*/
|
||||
void lv_mem_defrag(void);
|
||||
|
||||
/**
|
||||
* Give information about the work memory of dynamic allocation
|
||||
* @param mon_p pointer to a dm_mon_p variable,
|
||||
* the result of the analysis will be stored here
|
||||
*/
|
||||
void lv_mem_monitor(lv_mem_monitor_t * mon_p);
|
||||
|
||||
/**
|
||||
* Give the size of an allocated memory
|
||||
* @param data pointer to an allocated memory
|
||||
* @return the size of data memory in bytes
|
||||
*/
|
||||
uint32_t lv_mem_get_size(const void * data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Halt on NULL pointer
|
||||
* p pointer to a memory
|
||||
*/
|
||||
#if LV_USE_LOG == 0
|
||||
#define lv_mem_assert(p) \
|
||||
{ \
|
||||
if(p == NULL) \
|
||||
while(1) \
|
||||
; \
|
||||
}
|
||||
#else
|
||||
#define lv_mem_assert(p) \
|
||||
{ \
|
||||
if(p == NULL) { \
|
||||
LV_LOG_ERROR("Out of memory!"); \
|
||||
while(1) \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_MEM_H*/
|
||||
19
extended-setup/components/lvgl/src/lv_misc/lv_misc.mk
Normal file
19
extended-setup/components/lvgl/src/lv_misc/lv_misc.mk
Normal file
@@ -0,0 +1,19 @@
|
||||
CSRCS += lv_circ.c
|
||||
CSRCS += lv_area.c
|
||||
CSRCS += lv_task.c
|
||||
CSRCS += lv_fs.c
|
||||
CSRCS += lv_anim.c
|
||||
CSRCS += lv_mem.c
|
||||
CSRCS += lv_ll.c
|
||||
CSRCS += lv_color.c
|
||||
CSRCS += lv_txt.c
|
||||
CSRCS += lv_math.c
|
||||
CSRCS += lv_log.c
|
||||
CSRCS += lv_gc.c
|
||||
CSRCS += lv_utils.c
|
||||
CSRCS += lv_async.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_misc
|
||||
VPATH += :$(LVGL_DIR)/lvgl/src/lv_misc
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/lvgl/src/lv_misc"
|
||||
374
extended-setup/components/lvgl/src/lv_misc/lv_task.c
Normal file
374
extended-setup/components/lvgl/src/lv_misc/lv_task.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/**
|
||||
* @file lv_task.c
|
||||
* An 'lv_task' is a void (*fp) (void* param) type function which will be called periodically.
|
||||
* A priority (5 levels + disable) can be assigned to lv_tasks.
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_task.h"
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
#include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define IDLE_MEAS_PERIOD 500 /*[ms]*/
|
||||
#define DEF_PRIO LV_TASK_PRIO_MID
|
||||
#define DEF_PERIOD 500
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_task_exec(lv_task_t * task);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool lv_task_run = false;
|
||||
static uint8_t idle_last = 0;
|
||||
static bool task_deleted;
|
||||
static bool task_created;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init the lv_task module
|
||||
*/
|
||||
void lv_task_core_init(void)
|
||||
{
|
||||
lv_ll_init(&LV_GC_ROOT(_lv_task_ll), sizeof(lv_task_t));
|
||||
|
||||
/*Initially enable the lv_task handling*/
|
||||
lv_task_enable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call it periodically to handle lv_tasks.
|
||||
*/
|
||||
LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
{
|
||||
LV_LOG_TRACE("lv_task_handler started");
|
||||
|
||||
/*Avoid concurrent running of the task handler*/
|
||||
static bool task_handler_mutex = false;
|
||||
if(task_handler_mutex) return;
|
||||
task_handler_mutex = true;
|
||||
|
||||
static uint32_t idle_period_start = 0;
|
||||
static uint32_t handler_start = 0;
|
||||
static uint32_t busy_time = 0;
|
||||
|
||||
if(lv_task_run == false) {
|
||||
task_handler_mutex = false; /*Release mutex*/
|
||||
return;
|
||||
}
|
||||
|
||||
handler_start = lv_tick_get();
|
||||
|
||||
/* Run all task from the highest to the lowest priority
|
||||
* If a lower priority task is executed check task again from the highest priority
|
||||
* but on the priority of executed tasks don't run tasks before the executed*/
|
||||
lv_task_t * task_interrupter = NULL;
|
||||
lv_task_t * next;
|
||||
bool end_flag;
|
||||
do {
|
||||
end_flag = true;
|
||||
task_deleted = false;
|
||||
task_created = false;
|
||||
LV_GC_ROOT(_lv_task_act) = lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
|
||||
while(LV_GC_ROOT(_lv_task_act)) {
|
||||
/* The task might be deleted if it runs only once ('once = 1')
|
||||
* So get next element until the current is surely valid*/
|
||||
next = lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), LV_GC_ROOT(_lv_task_act));
|
||||
|
||||
/*We reach priority of the turned off task. There is nothing more to do.*/
|
||||
if(((lv_task_t *)LV_GC_ROOT(_lv_task_act))->prio == LV_TASK_PRIO_OFF) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*Here is the interrupter task. Don't execute it again.*/
|
||||
if(LV_GC_ROOT(_lv_task_act) == task_interrupter) {
|
||||
task_interrupter = NULL; /*From this point only task after the interrupter comes, so
|
||||
the interrupter is not interesting anymore*/
|
||||
LV_GC_ROOT(_lv_task_act) = next;
|
||||
continue; /*Load the next task*/
|
||||
}
|
||||
|
||||
/*Just try to run the tasks with highest priority.*/
|
||||
if(((lv_task_t *)LV_GC_ROOT(_lv_task_act))->prio == LV_TASK_PRIO_HIGHEST) {
|
||||
lv_task_exec(LV_GC_ROOT(_lv_task_act));
|
||||
}
|
||||
/*Tasks with higher priority then the interrupted shall be run in every case*/
|
||||
else if(task_interrupter) {
|
||||
if(((lv_task_t *)LV_GC_ROOT(_lv_task_act))->prio > task_interrupter->prio) {
|
||||
if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) {
|
||||
task_interrupter =
|
||||
LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */
|
||||
end_flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* It is no interrupter task or we already reached it earlier.
|
||||
* Just run the remaining tasks*/
|
||||
else {
|
||||
if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) {
|
||||
task_interrupter = LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */
|
||||
end_flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(task_deleted) break; /*If a task was deleted then this or the next item might be corrupted*/
|
||||
if(task_created) break; /*If a task was created then this or the next item might be corrupted*/
|
||||
|
||||
LV_GC_ROOT(_lv_task_act) = next; /*Load the next task*/
|
||||
}
|
||||
} while(!end_flag);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
task_handler_mutex = false; /*Release the mutex*/
|
||||
|
||||
LV_LOG_TRACE("lv_task_handler ready");
|
||||
}
|
||||
/**
|
||||
* Create an "empty" task. It needs to initialzed with at least
|
||||
* `lv_task_set_cb` and `lv_task_set_period`
|
||||
* @return pointer to the craeted task
|
||||
*/
|
||||
lv_task_t * lv_task_create_basic(void)
|
||||
{
|
||||
lv_task_t * new_task = NULL;
|
||||
lv_task_t * tmp;
|
||||
|
||||
/*Create task lists in order of priority from high to low*/
|
||||
tmp = lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
|
||||
|
||||
/*It's the first task*/
|
||||
if(NULL == tmp) {
|
||||
new_task = lv_ll_ins_head(&LV_GC_ROOT(_lv_task_ll));
|
||||
lv_mem_assert(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
}
|
||||
/*Insert the new task to proper place according to its priority*/
|
||||
else {
|
||||
do {
|
||||
if(tmp->prio <= DEF_PRIO) {
|
||||
new_task = lv_ll_ins_prev(&LV_GC_ROOT(_lv_task_ll), tmp);
|
||||
lv_mem_assert(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
break;
|
||||
}
|
||||
tmp = lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), tmp);
|
||||
} while(tmp != NULL);
|
||||
|
||||
/*Only too high priority tasks were found. Add the task to the end*/
|
||||
if(tmp == NULL) {
|
||||
new_task = lv_ll_ins_tail(&LV_GC_ROOT(_lv_task_ll));
|
||||
lv_mem_assert(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
new_task->period = DEF_PERIOD;
|
||||
new_task->task_cb = NULL;
|
||||
new_task->prio = DEF_PRIO;
|
||||
|
||||
new_task->once = 0;
|
||||
new_task->last_run = lv_tick_get();
|
||||
|
||||
new_task->user_data = NULL;
|
||||
|
||||
task_created = true;
|
||||
|
||||
return new_task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new lv_task
|
||||
* @param task_xcb a callback which is the task itself. It will be called periodically.
|
||||
* (the 'x' in the argument name indicates that its not a fully generic function because it not follows
|
||||
* the `func_name(object, callback, ...)` convention)
|
||||
* @param period call period in ms unit
|
||||
* @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped)
|
||||
* @param user_data custom parameter
|
||||
* @return pointer to the new task
|
||||
*/
|
||||
lv_task_t * lv_task_create(lv_task_cb_t task_cb, uint32_t period, lv_task_prio_t prio, void * user_data)
|
||||
{
|
||||
lv_task_t * new_task = lv_task_create_basic();
|
||||
lv_mem_assert(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
|
||||
lv_task_set_cb(new_task, task_cb);
|
||||
lv_task_set_period(new_task, period);
|
||||
lv_task_set_prio(new_task, prio);
|
||||
new_task->user_data = user_data;
|
||||
|
||||
return new_task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the callback the task (the function to call periodically)
|
||||
* @param task pointer to a task
|
||||
* @param task_cb teh function to call periodically
|
||||
*/
|
||||
void lv_task_set_cb(lv_task_t * task, lv_task_cb_t task_cb)
|
||||
{
|
||||
task->task_cb = task_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a lv_task
|
||||
* @param task pointer to task created by task
|
||||
*/
|
||||
void lv_task_del(lv_task_t * task)
|
||||
{
|
||||
lv_ll_rem(&LV_GC_ROOT(_lv_task_ll), task);
|
||||
|
||||
lv_mem_free(task);
|
||||
|
||||
if(LV_GC_ROOT(_lv_task_act) == task) task_deleted = true; /*The active task was deleted*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new priority for a lv_task
|
||||
* @param task pointer to a lv_task
|
||||
* @param prio the new priority
|
||||
*/
|
||||
void lv_task_set_prio(lv_task_t * task, lv_task_prio_t prio)
|
||||
{
|
||||
if(task->prio == prio) return;
|
||||
|
||||
/*Find the tasks with new priority*/
|
||||
lv_task_t * i;
|
||||
LV_LL_READ(LV_GC_ROOT(_lv_task_ll), i)
|
||||
{
|
||||
if(i->prio <= prio) {
|
||||
if(i != task) lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*There was no such a low priority so far then add the node to the tail*/
|
||||
if(i == NULL) {
|
||||
lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, NULL);
|
||||
}
|
||||
|
||||
task->prio = prio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new period for a lv_task
|
||||
* @param task pointer to a lv_task
|
||||
* @param period the new period
|
||||
*/
|
||||
void lv_task_set_period(lv_task_t * task, uint32_t period)
|
||||
{
|
||||
task->period = period;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a lv_task ready. It will not wait its period.
|
||||
* @param task pointer to a lv_task.
|
||||
*/
|
||||
void lv_task_ready(lv_task_t * task)
|
||||
{
|
||||
task->last_run = lv_tick_get() - task->period - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the lv_task after one call
|
||||
* @param task pointer to a lv_task.
|
||||
*/
|
||||
void lv_task_once(lv_task_t * task)
|
||||
{
|
||||
task->once = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset a lv_task.
|
||||
* It will be called the previously set period milliseconds later.
|
||||
* @param task pointer to a lv_task.
|
||||
*/
|
||||
void lv_task_reset(lv_task_t * task)
|
||||
{
|
||||
task->last_run = lv_tick_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the whole lv_task handling
|
||||
* @param en: true: lv_task handling is running, false: lv_task handling is suspended
|
||||
*/
|
||||
void lv_task_enable(bool en)
|
||||
{
|
||||
lv_task_run = en;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get idle percentage
|
||||
* @return the lv_task idle in percentage
|
||||
*/
|
||||
uint8_t lv_task_get_idle(void)
|
||||
{
|
||||
return idle_last;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Execute task if its the priority is appropriate
|
||||
* @param task pointer to lv_task
|
||||
* @return true: execute, false: not executed
|
||||
*/
|
||||
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) {
|
||||
task->last_run = lv_tick_get();
|
||||
task_deleted = false;
|
||||
task_created = false;
|
||||
if(task->task_cb) task->task_cb(task);
|
||||
|
||||
/*Delete if it was a one shot lv_task*/
|
||||
if(task_deleted == false) { /*The task might be deleted by itself as well*/
|
||||
if(task->once != 0) {
|
||||
lv_task_del(task);
|
||||
}
|
||||
}
|
||||
exec = true;
|
||||
}
|
||||
|
||||
return exec;
|
||||
}
|
||||
177
extended-setup/components/lvgl/src/lv_misc/lv_task.h
Normal file
177
extended-setup/components/lvgl/src/lv_misc/lv_task.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @file lv_task.c
|
||||
* An 'lv_task' is a void (*fp) (void* param) type function which will be called periodically.
|
||||
* A priority (5 levels + disable) can be assigned to lv_tasks.
|
||||
*/
|
||||
|
||||
#ifndef LV_TASK_H
|
||||
#define LV_TASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lv_mem.h"
|
||||
#include "lv_ll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_ATTRIBUTE_TASK_HANDLER
|
||||
#define LV_ATTRIBUTE_TASK_HANDLER
|
||||
#endif
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_task_t;
|
||||
|
||||
/**
|
||||
* Tasks execute this type type of functions.
|
||||
*/
|
||||
typedef void (*lv_task_cb_t)(struct _lv_task_t *);
|
||||
|
||||
/**
|
||||
* Possible priorities for lv_tasks
|
||||
*/
|
||||
enum {
|
||||
LV_TASK_PRIO_OFF = 0,
|
||||
LV_TASK_PRIO_LOWEST,
|
||||
LV_TASK_PRIO_LOW,
|
||||
LV_TASK_PRIO_MID,
|
||||
LV_TASK_PRIO_HIGH,
|
||||
LV_TASK_PRIO_HIGHEST,
|
||||
_LV_TASK_PRIO_NUM,
|
||||
};
|
||||
typedef uint8_t lv_task_prio_t;
|
||||
|
||||
/**
|
||||
* Descriptor of a lv_task
|
||||
*/
|
||||
typedef struct _lv_task_t
|
||||
{
|
||||
uint32_t period; /**< How often the task should run */
|
||||
uint32_t last_run; /**< Last time the task ran */
|
||||
lv_task_cb_t task_cb; /**< Task function */
|
||||
|
||||
void * user_data; /**< Custom user data */
|
||||
|
||||
uint8_t prio : 3; /**< Task priority */
|
||||
uint8_t once : 1; /**< 1: one shot task */
|
||||
} lv_task_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init the lv_task module
|
||||
*/
|
||||
void lv_task_core_init(void);
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
/**
|
||||
* Call it periodically to handle lv_tasks.
|
||||
*/
|
||||
LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
* Create an "empty" task. It needs to initialzed with at least
|
||||
* `lv_task_set_cb` and `lv_task_set_period`
|
||||
* @return pointer to the craeted task
|
||||
*/
|
||||
lv_task_t * lv_task_create_basic(void);
|
||||
|
||||
/**
|
||||
* Create a new lv_task
|
||||
* @param task_xcb a callback which is the task itself. It will be called periodically.
|
||||
* (the 'x' in the argument name indicates that its not a fully generic function because it not follows
|
||||
* the `func_name(object, callback, ...)` convention)
|
||||
* @param period call period in ms unit
|
||||
* @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped)
|
||||
* @param user_data custom parameter
|
||||
* @return pointer to the new task
|
||||
*/
|
||||
lv_task_t * lv_task_create(lv_task_cb_t task_xcb, uint32_t period, lv_task_prio_t prio, void * user_data);
|
||||
|
||||
/**
|
||||
* Delete a lv_task
|
||||
* @param task pointer to task_cb created by task
|
||||
*/
|
||||
void lv_task_del(lv_task_t * task);
|
||||
|
||||
/**
|
||||
* Set the callback the task (the function to call periodically)
|
||||
* @param task pointer to a task
|
||||
* @param task_cb the function to call periodically
|
||||
*/
|
||||
void lv_task_set_cb(lv_task_t * task, lv_task_cb_t task_cb);
|
||||
|
||||
/**
|
||||
* Set new priority for a lv_task
|
||||
* @param task pointer to a lv_task
|
||||
* @param prio the new priority
|
||||
*/
|
||||
void lv_task_set_prio(lv_task_t * task, lv_task_prio_t prio);
|
||||
|
||||
/**
|
||||
* Set new period for a lv_task
|
||||
* @param task pointer to a lv_task
|
||||
* @param period the new period
|
||||
*/
|
||||
void lv_task_set_period(lv_task_t * task, uint32_t period);
|
||||
|
||||
/**
|
||||
* Make a lv_task ready. It will not wait its period.
|
||||
* @param task pointer to a lv_task.
|
||||
*/
|
||||
void lv_task_ready(lv_task_t * task);
|
||||
|
||||
/**
|
||||
* Delete the lv_task after one call
|
||||
* @param task pointer to a lv_task.
|
||||
*/
|
||||
void lv_task_once(lv_task_t * task);
|
||||
|
||||
/**
|
||||
* Reset a lv_task.
|
||||
* It will be called the previously set period milliseconds later.
|
||||
* @param task pointer to a lv_task.
|
||||
*/
|
||||
void lv_task_reset(lv_task_t * task);
|
||||
|
||||
/**
|
||||
* Enable or disable the whole lv_task handling
|
||||
* @param en: true: lv_task handling is running, false: lv_task handling is suspended
|
||||
*/
|
||||
void lv_task_enable(bool en);
|
||||
|
||||
/**
|
||||
* Get idle percentage
|
||||
* @return the lv_task idle in percentage
|
||||
*/
|
||||
uint8_t lv_task_get_idle(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
40
extended-setup/components/lvgl/src/lv_misc/lv_templ.c
Normal file
40
extended-setup/components/lvgl/src/lv_misc/lv_templ.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file lv_templ.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* This typedef exists purely to keep -Wpedantic happy when the file is empty. */
|
||||
/* It can be removed. */
|
||||
typedef int keep_pedantic_happy;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
37
extended-setup/components/lvgl/src/lv_misc/lv_templ.h
Normal file
37
extended-setup/components/lvgl/src/lv_misc/lv_templ.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEMPL_H
|
||||
#define LV_TEMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEMPL_H*/
|
||||
729
extended-setup/components/lvgl/src/lv_misc/lv_txt.c
Normal file
729
extended-setup/components/lvgl/src/lv_misc/lv_txt.c
Normal file
@@ -0,0 +1,729 @@
|
||||
/**
|
||||
* @file lv_text.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_txt.h"
|
||||
#include "lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define NO_BREAK_FOUND UINT32_MAX
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static inline bool is_break_char(uint32_t letter);
|
||||
|
||||
#if LV_TXT_ENC == LV_TXT_ENC_UTF8
|
||||
static uint8_t lv_txt_utf8_size(const char * str);
|
||||
static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni);
|
||||
static uint32_t lv_txt_utf8_conv_wc(uint32_t c);
|
||||
static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i);
|
||||
static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i_start);
|
||||
static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id);
|
||||
static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id);
|
||||
static uint32_t lv_txt_utf8_get_length(const char * txt);
|
||||
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
|
||||
static uint8_t lv_txt_iso8859_1_size(const char * str);
|
||||
static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni);
|
||||
static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c);
|
||||
static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i);
|
||||
static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i_start);
|
||||
static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id);
|
||||
static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id);
|
||||
static uint32_t lv_txt_iso8859_1_get_length(const char * txt);
|
||||
#endif
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
#if LV_TXT_ENC == LV_TXT_ENC_UTF8
|
||||
uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_utf8_size;
|
||||
uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_utf8;
|
||||
uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_conv_wc;
|
||||
uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next;
|
||||
uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev;
|
||||
uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id;
|
||||
uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
|
||||
uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length;
|
||||
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
|
||||
uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size;
|
||||
uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_iso8859_1;
|
||||
uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_1_conv_wc;
|
||||
uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next;
|
||||
uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev;
|
||||
uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id;
|
||||
uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
|
||||
uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length;
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get size of a text
|
||||
* @param size_res pointer to a 'point_t' variable to store the result
|
||||
* @param text pointer to a text
|
||||
* @param font pinter to font of the text
|
||||
* @param letter_space letter space of the text
|
||||
* @param txt.line_space line space of the text
|
||||
* @param flags settings for the text from 'txt_flag_t' enum
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid
|
||||
* line breaks
|
||||
*/
|
||||
void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
|
||||
lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag)
|
||||
{
|
||||
size_res->x = 0;
|
||||
size_res->y = 0;
|
||||
|
||||
if(text == NULL) return;
|
||||
if(font == NULL) return;
|
||||
|
||||
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
||||
|
||||
uint32_t line_start = 0;
|
||||
uint32_t new_line_start = 0;
|
||||
lv_coord_t act_line_length;
|
||||
uint8_t letter_height = lv_font_get_line_height(font);
|
||||
|
||||
/*Calc. the height and longest line*/
|
||||
while(text[line_start] != '\0') {
|
||||
new_line_start += lv_txt_get_next_line(&text[line_start], font, letter_space, max_width, flag);
|
||||
size_res->y += letter_height;
|
||||
size_res->y += line_space;
|
||||
|
||||
/*Calculate the the longest line*/
|
||||
act_line_length = lv_txt_get_width(&text[line_start], new_line_start - line_start, font, letter_space, flag);
|
||||
|
||||
size_res->x = LV_MATH_MAX(act_line_length, size_res->x);
|
||||
line_start = new_line_start;
|
||||
}
|
||||
|
||||
/*Ma ke the text one line taller if the last character is '\n' or '\r'*/
|
||||
if((line_start != 0) && (text[line_start - 1] == '\n' || text[line_start - 1] == '\r')) {
|
||||
size_res->y += letter_height + line_space;
|
||||
}
|
||||
|
||||
/*Correction with the last line space or set the height manually if the text is empty*/
|
||||
if(size_res->y == 0)
|
||||
size_res->y = letter_height;
|
||||
else
|
||||
size_res->y -= line_space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next line of text. Check line length and break chars too.
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks
|
||||
* @param flags settings for the text from 'txt_flag_type' enum
|
||||
* @return the index of the first char of the new line (in byte index not letter index. With UTF-8 they are different)
|
||||
*/
|
||||
uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width,
|
||||
lv_txt_flag_t flag)
|
||||
{
|
||||
if(txt == NULL) return 0;
|
||||
if(font == NULL) return 0;
|
||||
|
||||
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t i_next = 0;
|
||||
lv_coord_t cur_w = 0;
|
||||
uint32_t last_break = NO_BREAK_FOUND;
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
uint32_t letter_w;
|
||||
uint32_t letter = 0;
|
||||
uint32_t letter_next = 0;
|
||||
|
||||
letter_next = lv_txt_encoded_next(txt, &i_next);
|
||||
|
||||
while(txt[i] != '\0') {
|
||||
letter = letter_next;
|
||||
i = i_next;
|
||||
letter_next = lv_txt_encoded_next(txt, &i_next);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
|
||||
continue; /*Skip the letter is it is part of a command*/
|
||||
}
|
||||
}
|
||||
|
||||
/*Check for new line chars*/
|
||||
if(letter == '\n' || letter == '\r') {
|
||||
/*Return with the first letter of the next line*/
|
||||
if(letter == '\r' && letter_next == '\n')
|
||||
return i_next;
|
||||
else
|
||||
return i;
|
||||
} else { /*Check the actual length*/
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
cur_w += letter_w;
|
||||
|
||||
/*If the txt is too long then finish, this is the line end*/
|
||||
if(cur_w > max_width) {
|
||||
/*If a break character was already found break there*/
|
||||
if(last_break != NO_BREAK_FOUND) {
|
||||
i = last_break;
|
||||
} else {
|
||||
/* Now this character is out of the area so it will be first character of the next line*/
|
||||
/* But 'i' already points to the next character (because of lv_txt_utf8_next) step beck one*/
|
||||
lv_txt_encoded_prev(txt, &i);
|
||||
}
|
||||
|
||||
/* Do not let to return without doing nothing.
|
||||
* Find at least one character (Avoid infinite loop )*/
|
||||
if(i == 0) lv_txt_encoded_next(txt, &i);
|
||||
|
||||
return i;
|
||||
}
|
||||
/*If this char still can fit to this line then check if
|
||||
* txt can be broken here later */
|
||||
else if(is_break_char(letter)) {
|
||||
last_break = i; /*Save the first char index after break*/
|
||||
}
|
||||
}
|
||||
|
||||
if(letter_w > 0) {
|
||||
cur_w += letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the length of a text with a given font
|
||||
* @param txt a '\0' terminate string
|
||||
* @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in
|
||||
* UTF-8)
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param flags settings for the text from 'txt_flag_t' enum
|
||||
* @return length of a char_num long text
|
||||
*/
|
||||
lv_coord_t lv_txt_get_width(const char * txt, uint16_t length, const lv_font_t * font, lv_coord_t letter_space,
|
||||
lv_txt_flag_t flag)
|
||||
{
|
||||
if(txt == NULL) return 0;
|
||||
if(font == NULL) return 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
lv_coord_t width = 0;
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
|
||||
if(length != 0) {
|
||||
while(i < length) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t char_width = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
if(char_width > 0) {
|
||||
width += char_width;
|
||||
width += letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
if(width > 0) {
|
||||
width -= letter_space; /*Trim the last letter space. Important if the text is center
|
||||
aligned */
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check next character in a string and decide if the character is part of the command or not
|
||||
* @param state pointer to a txt_cmd_state_t variable which stores the current state of command
|
||||
* processing (Initied. to TXT_CMD_STATE_WAIT )
|
||||
* @param c the current character
|
||||
* @return true: the character is part of a command and should not be written,
|
||||
* false: the character should be written
|
||||
*/
|
||||
bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if(c == (uint32_t)LV_TXT_COLOR_CMD[0]) {
|
||||
if(*state == LV_TXT_CMD_STATE_WAIT) { /*Start char*/
|
||||
*state = LV_TXT_CMD_STATE_PAR;
|
||||
ret = true;
|
||||
}
|
||||
/*Other start char in parameter is escaped cmd. char */
|
||||
else if(*state == LV_TXT_CMD_STATE_PAR) {
|
||||
*state = LV_TXT_CMD_STATE_WAIT;
|
||||
}
|
||||
/*Command end */
|
||||
else if(*state == LV_TXT_CMD_STATE_IN) {
|
||||
*state = LV_TXT_CMD_STATE_WAIT;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*Skip the color parameter and wait the space after it*/
|
||||
if(*state == LV_TXT_CMD_STATE_PAR) {
|
||||
if(c == ' ') {
|
||||
*state = LV_TXT_CMD_STATE_IN; /*After the parameter the text is in the command*/
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a string into an other
|
||||
* @param txt_buf the original text (must be big enough for the result text)
|
||||
* @param pos position to insert. Expressed in character index and not byte index (Different in
|
||||
* UTF-8) 0: before the original text, 1: after the first char etc.
|
||||
* @param ins_txt text to insert
|
||||
*/
|
||||
void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
|
||||
{
|
||||
uint32_t old_len = strlen(txt_buf);
|
||||
uint32_t ins_len = strlen(ins_txt);
|
||||
uint32_t new_len = ins_len + old_len;
|
||||
pos = lv_txt_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/
|
||||
|
||||
/*Copy the second part into the end to make place to text to insert*/
|
||||
uint32_t i;
|
||||
for(i = new_len; i >= pos + ins_len; i--) {
|
||||
txt_buf[i] = txt_buf[i - ins_len];
|
||||
}
|
||||
|
||||
/* Copy the text into the new space*/
|
||||
memcpy(txt_buf + pos, ins_txt, ins_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a part of a string
|
||||
* @param txt string to modify
|
||||
* @param pos position where to start the deleting (0: before the first char, 1: after the first
|
||||
* char etc.)
|
||||
* @param len number of characters to delete
|
||||
*/
|
||||
void lv_txt_cut(char * txt, uint32_t pos, uint32_t len)
|
||||
{
|
||||
|
||||
uint32_t old_len = strlen(txt);
|
||||
|
||||
pos = lv_txt_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/
|
||||
len = lv_txt_encoded_get_byte_id(&txt[pos], len);
|
||||
|
||||
/*Copy the second part into the end to make place to text to insert*/
|
||||
uint32_t i;
|
||||
for(i = pos; i <= old_len - len; i++) {
|
||||
txt[i] = txt[i + len];
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_TXT_ENC == LV_TXT_ENC_UTF8
|
||||
/*******************************
|
||||
* UTF-8 ENCODER/DECOER
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* Give the size of an UTF-8 coded character
|
||||
* @param str pointer to a character in a string
|
||||
* @return length of the UTF-8 character (1,2,3 or 4). O on invalid code
|
||||
*/
|
||||
static uint8_t lv_txt_utf8_size(const char * str)
|
||||
{
|
||||
if((str[0] & 0x80) == 0)
|
||||
return 1;
|
||||
else if((str[0] & 0xE0) == 0xC0)
|
||||
return 2;
|
||||
else if((str[0] & 0xF0) == 0xE0)
|
||||
return 3;
|
||||
else if((str[0] & 0xF8) == 0xF0)
|
||||
return 4;
|
||||
return 1; /*If the char was invalid step tell it's 1 byte long*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an Unicode letter to UTF-8.
|
||||
* @param letter_uni an Unicode letter
|
||||
* @return UTF-8 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű')
|
||||
*/
|
||||
static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni)
|
||||
{
|
||||
if(letter_uni < 128) return letter_uni;
|
||||
uint8_t bytes[4];
|
||||
|
||||
if(letter_uni < 0x0800) {
|
||||
bytes[0] = ((letter_uni >> 6) & 0x1F) | 0xC0;
|
||||
bytes[1] = ((letter_uni >> 0) & 0x3F) | 0x80;
|
||||
bytes[2] = 0;
|
||||
bytes[3] = 0;
|
||||
} else if(letter_uni < 0x010000) {
|
||||
bytes[0] = ((letter_uni >> 12) & 0x0F) | 0xE0;
|
||||
bytes[1] = ((letter_uni >> 6) & 0x3F) | 0x80;
|
||||
bytes[2] = ((letter_uni >> 0) & 0x3F) | 0x80;
|
||||
bytes[3] = 0;
|
||||
} else if(letter_uni < 0x110000) {
|
||||
bytes[0] = ((letter_uni >> 18) & 0x07) | 0xF0;
|
||||
bytes[1] = ((letter_uni >> 12) & 0x3F) | 0x80;
|
||||
bytes[2] = ((letter_uni >> 6) & 0x3F) | 0x80;
|
||||
bytes[3] = ((letter_uni >> 0) & 0x3F) | 0x80;
|
||||
}
|
||||
|
||||
uint32_t * res_p = (uint32_t *)bytes;
|
||||
return *res_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a wide character, e.g. 'Á' little endian to be UTF-8 compatible
|
||||
* @param c a wide character or a Little endian number
|
||||
* @return `c` in big endian
|
||||
*/
|
||||
static uint32_t lv_txt_utf8_conv_wc(uint32_t c)
|
||||
{
|
||||
/*Swap the bytes (UTF-8 is big endian, but the MCUs are little endian)*/
|
||||
if((c & 0x80) != 0) {
|
||||
uint32_t swapped;
|
||||
uint8_t c8[4];
|
||||
memcpy(c8, &c, 4);
|
||||
swapped = (c8[0] << 24) + (c8[1] << 16) + (c8[2] << 8) + (c8[3]);
|
||||
uint8_t i;
|
||||
for(i = 0; i < 4; i++) {
|
||||
if((swapped & 0xFF) == 0)
|
||||
swapped = (swapped >> 8); /*Ignore leading zeros (they were in the end originally)*/
|
||||
}
|
||||
c = swapped;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an UTF-8 character from a string.
|
||||
* @param txt pointer to '\0' terminated string
|
||||
* @param i start byte index in 'txt' where to start.
|
||||
* After call it will point to the next UTF-8 char in 'txt'.
|
||||
* NULL to use txt[0] as index
|
||||
* @return the decoded Unicode character or 0 on invalid UTF-8 code
|
||||
*/
|
||||
static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i)
|
||||
{
|
||||
/* Unicode to UTF-8
|
||||
* 00000000 00000000 00000000 0xxxxxxx -> 0xxxxxxx
|
||||
* 00000000 00000000 00000yyy yyxxxxxx -> 110yyyyy 10xxxxxx
|
||||
* 00000000 00000000 zzzzyyyy yyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx
|
||||
* 00000000 000wwwzz zzzzyyyy yyxxxxxx -> 11110www 10zzzzzz 10yyyyyy 10xxxxxx
|
||||
* */
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
/*Dummy 'i' pointer is required*/
|
||||
uint32_t i_tmp = 0;
|
||||
if(i == NULL) i = &i_tmp;
|
||||
|
||||
/*Normal ASCII*/
|
||||
if((txt[*i] & 0x80) == 0) {
|
||||
result = txt[*i];
|
||||
(*i)++;
|
||||
}
|
||||
/*Real UTF-8 decode*/
|
||||
else {
|
||||
/*2 bytes UTF-8 code*/
|
||||
if((txt[*i] & 0xE0) == 0xC0) {
|
||||
result = (uint32_t)(txt[*i] & 0x1F) << 6;
|
||||
(*i)++;
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
result += (txt[*i] & 0x3F);
|
||||
(*i)++;
|
||||
}
|
||||
/*3 bytes UTF-8 code*/
|
||||
else if((txt[*i] & 0xF0) == 0xE0) {
|
||||
result = (uint32_t)(txt[*i] & 0x0F) << 12;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
result += (uint32_t)(txt[*i] & 0x3F) << 6;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
result += (txt[*i] & 0x3F);
|
||||
(*i)++;
|
||||
}
|
||||
/*4 bytes UTF-8 code*/
|
||||
else if((txt[*i] & 0xF8) == 0xF0) {
|
||||
result = (uint32_t)(txt[*i] & 0x07) << 18;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
result += (uint32_t)(txt[*i] & 0x3F) << 12;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
result += (uint32_t)(txt[*i] & 0x3F) << 6;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
result += txt[*i] & 0x3F;
|
||||
(*i)++;
|
||||
} else {
|
||||
(*i)++; /*Not UTF-8 char. Go the next.*/
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get previous UTF-8 character form a string.
|
||||
* @param txt pointer to '\0' terminated string
|
||||
* @param i start byte index in 'txt' where to start. After the call it will point to the previous
|
||||
* UTF-8 char in 'txt'.
|
||||
* @return the decoded Unicode character or 0 on invalid UTF-8 code
|
||||
*/
|
||||
static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i)
|
||||
{
|
||||
uint8_t c_size;
|
||||
uint8_t cnt = 0;
|
||||
|
||||
/*Try to find a !0 long UTF-8 char by stepping one character back*/
|
||||
(*i)--;
|
||||
do {
|
||||
if(cnt >= 4) return 0; /*No UTF-8 char found before the initial*/
|
||||
|
||||
c_size = lv_txt_encoded_size(&txt[*i]);
|
||||
if(c_size == 0) {
|
||||
if(*i != 0)
|
||||
(*i)--;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
cnt++;
|
||||
} while(c_size == 0);
|
||||
|
||||
uint32_t i_tmp = *i;
|
||||
uint32_t letter = lv_txt_encoded_next(txt, &i_tmp); /*Character found, get it*/
|
||||
|
||||
return letter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a character index (in an UTF-8 text) to byte index.
|
||||
* E.g. in "AÁRT" index of 'R' is 2th char but start at byte 3 because 'Á' is 2 bytes long
|
||||
* @param txt a '\0' terminated UTF-8 string
|
||||
* @param utf8_id character index
|
||||
* @return byte index of the 'utf8_id'th letter
|
||||
*/
|
||||
static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t byte_cnt = 0;
|
||||
for(i = 0; i < utf8_id; i++) {
|
||||
byte_cnt += lv_txt_encoded_size(&txt[byte_cnt]);
|
||||
}
|
||||
|
||||
return byte_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a byte index (in an UTF-8 text) to character index.
|
||||
* E.g. in "AÁRT" index of 'R' is 2th char but start at byte 3 because 'Á' is 2 bytes long
|
||||
* @param txt a '\0' terminated UTF-8 string
|
||||
* @param byte_id byte index
|
||||
* @return character index of the letter at 'byte_id'th position
|
||||
*/
|
||||
static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t char_cnt = 0;
|
||||
|
||||
while(i < byte_id) {
|
||||
lv_txt_encoded_next(txt, &i); /*'i' points to the next letter so use the prev. value*/
|
||||
char_cnt++;
|
||||
}
|
||||
|
||||
return char_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of characters (and NOT bytes) in a string. Decode it with UTF-8 if enabled.
|
||||
* E.g.: "ÁBC" is 3 characters (but 4 bytes)
|
||||
* @param txt a '\0' terminated char string
|
||||
* @return number of characters
|
||||
*/
|
||||
static uint32_t lv_txt_utf8_get_length(const char * txt)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
while(txt[i] != '\0') {
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
|
||||
/*******************************
|
||||
* ASCII ENCODER/DECOER
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* Give the size of an ISO8859-1 coded character
|
||||
* @param str pointer to a character in a string
|
||||
* @return length of the UTF-8 character (1,2,3 or 4). O on invalid code
|
||||
*/
|
||||
static uint8_t lv_txt_iso8859_1_size(const char * str)
|
||||
{
|
||||
(void)str; /*Unused*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an Unicode letter to ISO8859-1.
|
||||
* @param letter_uni an Unicode letter
|
||||
* @return ISO8859-1 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű')
|
||||
*/
|
||||
static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni)
|
||||
{
|
||||
if(letter_uni < 128)
|
||||
return letter_uni;
|
||||
else
|
||||
return ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert wide characters to ASCII, however wide characters in ASCII range (e.g. 'A') are ASCII compatible by default.
|
||||
* So this function does nothing just returns with `c`.
|
||||
* @param c a character, e.g. 'A'
|
||||
* @return same as `c`
|
||||
*/
|
||||
static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an ISO8859-1 character from a string.
|
||||
* @param txt pointer to '\0' terminated string
|
||||
* @param i start byte index in 'txt' where to start.
|
||||
* After call it will point to the next UTF-8 char in 'txt'.
|
||||
* NULL to use txt[0] as index
|
||||
* @return the decoded Unicode character or 0 on invalid UTF-8 code
|
||||
*/
|
||||
static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i)
|
||||
{
|
||||
if(i == NULL) return txt[1]; /*Get the next char */
|
||||
|
||||
uint8_t letter = txt[*i];
|
||||
(*i)++;
|
||||
return letter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get previous ISO8859-1 character form a string.
|
||||
* @param txt pointer to '\0' terminated string
|
||||
* @param i start byte index in 'txt' where to start. After the call it will point to the previous UTF-8 char in 'txt'.
|
||||
* @return the decoded Unicode character or 0 on invalid UTF-8 code
|
||||
*/
|
||||
static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i)
|
||||
{
|
||||
if(i == NULL) return *(txt - 1); /*Get the prev. char */
|
||||
|
||||
(*i)--;
|
||||
uint8_t letter = txt[*i];
|
||||
|
||||
return letter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a character index (in an ISO8859-1 text) to byte index.
|
||||
* E.g. in "AÁRT" index of 'R' is 2th char but start at byte 3 because 'Á' is 2 bytes long
|
||||
* @param txt a '\0' terminated UTF-8 string
|
||||
* @param utf8_id character index
|
||||
* @return byte index of the 'utf8_id'th letter
|
||||
*/
|
||||
static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id)
|
||||
{
|
||||
(void)txt; /*Unused*/
|
||||
return utf8_id; /*In Non encoded no difference*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a byte index (in an ISO8859-1 text) to character index.
|
||||
* E.g. in "AÁRT" index of 'R' is 2th char but start at byte 3 because 'Á' is 2 bytes long
|
||||
* @param txt a '\0' terminated UTF-8 string
|
||||
* @param byte_id byte index
|
||||
* @return character index of the letter at 'byte_id'th position
|
||||
*/
|
||||
static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id)
|
||||
{
|
||||
(void)txt; /*Unused*/
|
||||
return byte_id; /*In Non encoded no difference*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of characters (and NOT bytes) in a string. Decode it with UTF-8 if enabled.
|
||||
* E.g.: "ÁBC" is 3 characters (but 4 bytes)
|
||||
* @param txt a '\0' terminated char string
|
||||
* @return number of characters
|
||||
*/
|
||||
static uint32_t lv_txt_iso8859_1_get_length(const char * txt)
|
||||
{
|
||||
return strlen(txt);
|
||||
}
|
||||
#else
|
||||
|
||||
#error "Invalid character encoding. See `LV_TXT_ENC` in `lv_conf.h`"
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Test if char is break char or not (a text can broken here or not)
|
||||
* @param letter a letter
|
||||
* @return false: 'letter' is not break char
|
||||
*/
|
||||
static inline bool is_break_char(uint32_t letter)
|
||||
{
|
||||
uint8_t i;
|
||||
bool ret = false;
|
||||
|
||||
/*Compare the letter to TXT_BREAK_CHARS*/
|
||||
for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) {
|
||||
if(letter == (uint32_t)LV_TXT_BREAK_CHARS[i]) {
|
||||
ret = true; /*If match then it is break char*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
209
extended-setup/components/lvgl/src/lv_misc/lv_txt.h
Normal file
209
extended-setup/components/lvgl/src/lv_misc/lv_txt.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* @file lv_text.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TXT_H
|
||||
#define LV_TXT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "lv_area.h"
|
||||
#include "lv_area.h"
|
||||
#include "../lv_font/lv_font.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
|
||||
#define LV_TXT_ENC_UTF8 1
|
||||
#define LV_TXT_ENC_ASCII 2
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/**
|
||||
* Options for text rendering.
|
||||
*/
|
||||
enum {
|
||||
LV_TXT_FLAG_NONE = 0x00,
|
||||
LV_TXT_FLAG_RECOLOR = 0x01, /**< Enable parsing of recolor command*/
|
||||
LV_TXT_FLAG_EXPAND = 0x02, /**< Ignore width to avoid automatic word wrapping*/
|
||||
LV_TXT_FLAG_CENTER = 0x04, /**< Align the text to the middle*/
|
||||
LV_TXT_FLAG_RIGHT = 0x08, /**< Align the text to the right*/
|
||||
};
|
||||
typedef uint8_t lv_txt_flag_t;
|
||||
|
||||
/**
|
||||
* State machine for text renderer. */
|
||||
enum {
|
||||
LV_TXT_CMD_STATE_WAIT, /**< Waiting for command*/
|
||||
LV_TXT_CMD_STATE_PAR, /**< Processing the parameter*/
|
||||
LV_TXT_CMD_STATE_IN, /**< Processing the command*/
|
||||
};
|
||||
typedef uint8_t lv_txt_cmd_state_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get size of a text
|
||||
* @param size_res pointer to a 'point_t' variable to store the result
|
||||
* @param text pointer to a text
|
||||
* @param font pinter to font of the text
|
||||
* @param letter_space letter space of the text
|
||||
* @param line_space line space of the text
|
||||
* @param flags settings for the text from 'txt_flag_t' enum
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid
|
||||
* line breaks
|
||||
*/
|
||||
void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
|
||||
lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag);
|
||||
|
||||
/**
|
||||
* Get the next line of text. Check line length and break chars too.
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid
|
||||
* line breaks
|
||||
* @param flags settings for the text from 'txt_flag_type' enum
|
||||
* @return the index of the first char of the new line (in byte index not letter index. With UTF-8
|
||||
* they are different)
|
||||
*/
|
||||
uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width,
|
||||
lv_txt_flag_t flag);
|
||||
|
||||
/**
|
||||
* Give the length of a text with a given font
|
||||
* @param txt a '\0' terminate string
|
||||
* @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in
|
||||
* UTF-8)
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param flags settings for the text from 'txt_flag_t' enum
|
||||
* @return length of a char_num long text
|
||||
*/
|
||||
lv_coord_t lv_txt_get_width(const char * txt, uint16_t length, const lv_font_t * font, lv_coord_t letter_space,
|
||||
lv_txt_flag_t flag);
|
||||
|
||||
/**
|
||||
* Check next character in a string and decide if te character is part of the command or not
|
||||
* @param state pointer to a txt_cmd_state_t variable which stores the current state of command
|
||||
* processing
|
||||
* @param c the current character
|
||||
* @return true: the character is part of a command and should not be written,
|
||||
* false: the character should be written
|
||||
*/
|
||||
bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c);
|
||||
|
||||
/**
|
||||
* Insert a string into an other
|
||||
* @param txt_buf the original text (must be big enough for the result text)
|
||||
* @param pos position to insert (0: before the original text, 1: after the first char etc.)
|
||||
* @param ins_txt text to insert
|
||||
*/
|
||||
void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt);
|
||||
|
||||
/**
|
||||
* Delete a part of a string
|
||||
* @param txt string to modify
|
||||
* @param pos position where to start the deleting (0: before the first char, 1: after the first
|
||||
* char etc.)
|
||||
* @param len number of characters to delete
|
||||
*/
|
||||
void lv_txt_cut(char * txt, uint32_t pos, uint32_t len);
|
||||
|
||||
/***************************************************************
|
||||
* GLOBAL FUNCTION POINTERS FOR CAHRACTER ENCODING INTERFACE
|
||||
***************************************************************/
|
||||
|
||||
/**
|
||||
* Give the size of an encoded character
|
||||
* @param str pointer to a character in a string
|
||||
* @return length of the encoded character (1,2,3 ...). O in invalid
|
||||
*/
|
||||
extern uint8_t (*lv_txt_encoded_size)(const char *);
|
||||
|
||||
/**
|
||||
* Convert an Unicode letter to encoded
|
||||
* @param letter_uni an Unicode letter
|
||||
* @return Encoded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ü')
|
||||
*/
|
||||
extern uint32_t (*lv_txt_unicode_to_encoded)(uint32_t);
|
||||
|
||||
/**
|
||||
* Convert a wide character, e.g. 'Á' little endian to be compatible with the encoded format.
|
||||
* @param c a wide character
|
||||
* @return `c` in the encoded format
|
||||
*/
|
||||
extern uint32_t (*lv_txt_encoded_conv_wc)(uint32_t c);
|
||||
|
||||
/**
|
||||
* Decode the next encoded character from a string.
|
||||
* @param txt pointer to '\0' terminated string
|
||||
* @param i start index in 'txt' where to start.
|
||||
* After the call it will point to the next encoded char in 'txt'.
|
||||
* NULL to use txt[0] as index
|
||||
* @return the decoded Unicode character or 0 on invalid data code
|
||||
*/
|
||||
extern uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *);
|
||||
|
||||
/**
|
||||
* Get the previous encoded character form a string.
|
||||
* @param txt pointer to '\0' terminated string
|
||||
* @param i_start index in 'txt' where to start. After the call it will point to the previous
|
||||
* encoded char in 'txt'.
|
||||
* @return the decoded Unicode character or 0 on invalid data
|
||||
*/
|
||||
extern uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *);
|
||||
|
||||
/**
|
||||
* Convert a letter index (in an the encoded text) to byte index.
|
||||
* E.g. in UTF-8 "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long
|
||||
* @param txt a '\0' terminated UTF-8 string
|
||||
* @param enc_id letter index
|
||||
* @return byte index of the 'enc_id'th letter
|
||||
*/
|
||||
extern uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t);
|
||||
|
||||
/**
|
||||
* Convert a byte index (in an encoded text) to character index.
|
||||
* E.g. in UTF-8 "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long
|
||||
* @param txt a '\0' terminated UTF-8 string
|
||||
* @param byte_id byte index
|
||||
* @return character index of the letter at 'byte_id'th position
|
||||
*/
|
||||
extern uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t);
|
||||
|
||||
/**
|
||||
* Get the number of characters (and NOT bytes) in a string.
|
||||
* E.g. in UTF-8 "ÁBC" is 3 characters (but 4 bytes)
|
||||
* @param txt a '\0' terminated char string
|
||||
* @return number of characters
|
||||
*/
|
||||
extern uint32_t (*lv_txt_get_encoded_length)(const char *);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*USE_TXT*/
|
||||
49
extended-setup/components/lvgl/src/lv_misc/lv_types.h
Normal file
49
extended-setup/components/lvgl/src/lv_misc/lv_types.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file lv_types.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TYPES_H
|
||||
#define LV_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* LittlevGL error codes.
|
||||
*/
|
||||
enum {
|
||||
LV_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action
|
||||
function or an operation was failed*/
|
||||
LV_RES_OK, /*The object is valid (no deleted) after the action*/
|
||||
};
|
||||
typedef uint8_t lv_res_t;
|
||||
|
||||
typedef unsigned long int lv_uintptr_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TYPES_H*/
|
||||
115
extended-setup/components/lvgl/src/lv_misc/lv_utils.c
Normal file
115
extended-setup/components/lvgl/src/lv_misc/lv_utils.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @file lv_utils.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lv_utils.h"
|
||||
#include "lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert a number to string
|
||||
* @param num a number
|
||||
* @param buf pointer to a `char` buffer. The result will be stored here (max 10 elements)
|
||||
* @return same as `buf` (just for convenience)
|
||||
*/
|
||||
char * lv_utils_num_to_str(int32_t num, char * buf)
|
||||
{
|
||||
if(num == 0) {
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
int8_t digitCount = 0;
|
||||
int8_t i = 0;
|
||||
if(num < 0) {
|
||||
buf[digitCount++] = '-';
|
||||
num = LV_MATH_ABS(num);
|
||||
++i;
|
||||
}
|
||||
while(num) {
|
||||
char digit = num % 10;
|
||||
buf[digitCount++] = digit + 48;
|
||||
num /= 10;
|
||||
}
|
||||
buf[digitCount] = '\0';
|
||||
digitCount--;
|
||||
while(digitCount > i) {
|
||||
char temp = buf[i];
|
||||
buf[i] = buf[digitCount];
|
||||
buf[digitCount] = temp;
|
||||
digitCount--;
|
||||
i++;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Searches base[0] to base[n - 1] for an item that matches *key.
|
||||
*
|
||||
* @note The function cmp must return negative if its first
|
||||
* argument (the search key) is less that its second (a table entry),
|
||||
* zero if equal, and positive if greater.
|
||||
*
|
||||
* @note Items in the array must be in ascending order.
|
||||
*
|
||||
* @param key Pointer to item being searched for
|
||||
* @param base Pointer to first element to search
|
||||
* @param n Number of elements
|
||||
* @param size Size of each element
|
||||
* @param cmp Pointer to comparison function (see #lv_font_codeCompare as a comparison function
|
||||
* example)
|
||||
*
|
||||
* @return a pointer to a matching item, or NULL if none exists.
|
||||
*/
|
||||
void * lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_t size,
|
||||
int32_t (*cmp)(const void * pRef, const void * pElement))
|
||||
{
|
||||
const char * middle;
|
||||
int32_t c;
|
||||
|
||||
for(middle = base; n != 0;) {
|
||||
middle += (n / 2) * size;
|
||||
if((c = (*cmp)(key, middle)) > 0) {
|
||||
n = (n / 2) - ((n & 1) == 0);
|
||||
base = (middle += size);
|
||||
} else if(c < 0) {
|
||||
n /= 2;
|
||||
middle = base;
|
||||
} else {
|
||||
return (char *)middle;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
66
extended-setup/components/lvgl/src/lv_misc/lv_utils.h
Normal file
66
extended-setup/components/lvgl/src/lv_misc/lv_utils.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file lv_utils.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_UTILS_H
|
||||
#define LV_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
/**
|
||||
* Convert a number to string
|
||||
* @param num a number
|
||||
* @param buf pointer to a `char` buffer. The result will be stored here (max 10 elements)
|
||||
* @return same as `buf` (just for convenience)
|
||||
*/
|
||||
char * lv_utils_num_to_str(int32_t num, char * buf);
|
||||
|
||||
/** Searches base[0] to base[n - 1] for an item that matches *key.
|
||||
*
|
||||
* @note The function cmp must return negative if its first
|
||||
* argument (the search key) is less that its second (a table entry),
|
||||
* zero if equal, and positive if greater.
|
||||
*
|
||||
* @note Items in the array must be in ascending order.
|
||||
*
|
||||
* @param key Pointer to item being searched for
|
||||
* @param base Pointer to first element to search
|
||||
* @param n Number of elements
|
||||
* @param size Size of each element
|
||||
* @param cmp Pointer to comparison function (see #lv_font_codeCompare as a comparison function
|
||||
* example)
|
||||
*
|
||||
* @return a pointer to a matching item, or NULL if none exists.
|
||||
*/
|
||||
void * lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_t size,
|
||||
int32_t (*cmp)(const void * pRef, const void * pElement));
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user