Files
STM32F4-Base/Lib/lvgl/src/misc/lv_circle_buf.c
T
2026-08-30 08:57:07 +08:00

296 lines
6.8 KiB
C

/**
* @file lv_circle_buf.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_assert.h"
#include "lv_circle_buf.h"
#include "lv_array.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_circle_buf_t {
lv_array_t array;
uint32_t head;
uint32_t tail; /**< The next write position */
bool inner_alloc; /**< true: the array is allocated by the buffer, false: the array is created from an external buffer */
};
/**********************
* STATIC PROTOTYPES
**********************/
static void circle_buf_prepare_empty(lv_circle_buf_t * circle_buf);
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_circle_buf_t * lv_circle_buf_create(const uint32_t capacity, const uint32_t element_size)
{
lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
LV_ASSERT_MALLOC(circle_buf);
if(circle_buf == NULL) {
return NULL;
}
lv_array_init(&circle_buf->array, capacity, element_size);
circle_buf->head = 0;
circle_buf->tail = 0;
circle_buf->inner_alloc = true;
circle_buf_prepare_empty(circle_buf);
return circle_buf;
}
lv_circle_buf_t * lv_circle_buf_create_from_buf(void * buf, const uint32_t capacity, const uint32_t element_size)
{
LV_ASSERT_NULL(buf);
lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
LV_ASSERT_MALLOC(circle_buf);
if(circle_buf == NULL) {
return NULL;
}
lv_array_init_from_buf(&circle_buf->array, buf, capacity, element_size);
circle_buf->head = 0;
circle_buf->tail = 0;
circle_buf->inner_alloc = false;
circle_buf_prepare_empty(circle_buf);
return circle_buf;
}
lv_circle_buf_t * lv_circle_buf_create_from_array(const lv_array_t * array)
{
LV_ASSERT_NULL(array);
if(array == NULL) {
return NULL;
}
lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
LV_ASSERT_MALLOC(circle_buf);
if(circle_buf == NULL) {
return NULL;
}
circle_buf->array = *array;
circle_buf->head = 0;
circle_buf->tail = 0;
circle_buf->inner_alloc = false;
circle_buf_prepare_empty(circle_buf);
return circle_buf;
}
lv_result_t lv_circle_buf_resize(lv_circle_buf_t * circle_buf, const uint32_t capacity)
{
LV_ASSERT_NULL(circle_buf);
if(lv_array_resize(&circle_buf->array, capacity) == false) {
return LV_RESULT_INVALID;
}
circle_buf->head = 0;
circle_buf->tail = 0;
circle_buf_prepare_empty(circle_buf);
return LV_RESULT_OK;
}
void lv_circle_buf_destroy(lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
lv_array_deinit(&circle_buf->array);
lv_free(circle_buf);
}
uint32_t lv_circle_buf_size(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return circle_buf->tail - circle_buf->head;
}
uint32_t lv_circle_buf_capacity(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return lv_array_capacity(&circle_buf->array);
}
uint32_t lv_circle_buf_remain(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return lv_circle_buf_capacity(circle_buf) - lv_circle_buf_size(circle_buf);
}
bool lv_circle_buf_is_empty(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return !lv_circle_buf_size(circle_buf);
}
bool lv_circle_buf_is_full(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return !lv_circle_buf_remain(circle_buf);
}
void lv_circle_buf_reset(lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
circle_buf->head = 0;
circle_buf->tail = 0;
}
void * lv_circle_buf_head(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return lv_array_at(&circle_buf->array,
circle_buf->head % lv_circle_buf_capacity(circle_buf));
}
void * lv_circle_buf_tail(const lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
return lv_array_at(&circle_buf->array,
circle_buf->tail % lv_circle_buf_capacity(circle_buf));
}
lv_result_t lv_circle_buf_read(lv_circle_buf_t * circle_buf, void * data)
{
LV_ASSERT_NULL(circle_buf);
if(lv_circle_buf_is_empty(circle_buf)) {
circle_buf->head = 0;
circle_buf->tail = 0;
return LV_RESULT_INVALID;
}
lv_circle_buf_peek_at(circle_buf, 0, data);
circle_buf->head++;
return LV_RESULT_OK;
}
lv_result_t lv_circle_buf_write(lv_circle_buf_t * circle_buf, const void * data)
{
LV_ASSERT_NULL(circle_buf);
if(lv_circle_buf_is_full(circle_buf)) {
return LV_RESULT_INVALID;
}
lv_array_assign(&circle_buf->array, circle_buf->tail % lv_circle_buf_capacity(circle_buf), data);
circle_buf->tail++;
return LV_RESULT_OK;
}
uint32_t lv_circle_buf_fill(lv_circle_buf_t * circle_buf, uint32_t count, lv_circle_buf_fill_cb_t fill_cb,
void * user_data)
{
LV_ASSERT_NULL(circle_buf);
LV_ASSERT_NULL(fill_cb);
uint32_t filled = 0;
while(count > 0 && !lv_circle_buf_is_full(circle_buf)) {
void * data = lv_circle_buf_tail(circle_buf);
if(fill_cb(data, circle_buf->array.element_size, (int32_t)filled, user_data) == LV_RESULT_OK) {
circle_buf->tail++;
filled++;
}
else break;
count--;
}
return filled;
}
lv_result_t lv_circle_buf_skip(lv_circle_buf_t * circle_buf)
{
LV_ASSERT_NULL(circle_buf);
if(lv_circle_buf_is_empty(circle_buf)) {
circle_buf->head = 0;
circle_buf->tail = 0;
return LV_RESULT_INVALID;
}
circle_buf->head++;
return LV_RESULT_OK;
}
lv_result_t lv_circle_buf_peek(const lv_circle_buf_t * circle_buf, void * data)
{
LV_ASSERT_NULL(circle_buf);
LV_ASSERT_NULL(data);
return lv_circle_buf_peek_at(circle_buf, 0, data);
}
lv_result_t lv_circle_buf_peek_at(const lv_circle_buf_t * circle_buf, const uint32_t index, void * data)
{
LV_ASSERT_NULL(circle_buf);
LV_ASSERT_NULL(data);
const uint32_t real_index = (index % lv_circle_buf_size(circle_buf) + circle_buf->head) % lv_circle_buf_capacity(
circle_buf);
lv_memcpy(data, lv_array_at(&circle_buf->array, real_index), circle_buf->array.element_size);
return LV_RESULT_OK;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void circle_buf_prepare_empty(lv_circle_buf_t * circle_buf)
{
const uint32_t required = lv_array_capacity(&circle_buf->array) - lv_array_size(&circle_buf->array);
for(uint32_t i = 0; i < required; i++) lv_array_push_back(&circle_buf->array, NULL);
}