feat(circle_buff): add lv_circle_buf_t component
This commit is contained in:
1
lvgl.h
1
lvgl.h
@@ -34,6 +34,7 @@ extern "C" {
|
|||||||
#include "src/misc/lv_rb.h"
|
#include "src/misc/lv_rb.h"
|
||||||
#include "src/misc/lv_utils.h"
|
#include "src/misc/lv_utils.h"
|
||||||
#include "src/misc/lv_iter.h"
|
#include "src/misc/lv_iter.h"
|
||||||
|
#include "src/misc/lv_circle_buf.h"
|
||||||
|
|
||||||
#include "src/tick/lv_tick.h"
|
#include "src/tick/lv_tick.h"
|
||||||
|
|
||||||
|
|||||||
@@ -42,13 +42,25 @@ void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size)
|
|||||||
array->element_size = element_size;
|
array->element_size = element_size;
|
||||||
|
|
||||||
array->data = lv_malloc(capacity * element_size);
|
array->data = lv_malloc(capacity * element_size);
|
||||||
|
array->inner_alloc = true;
|
||||||
LV_ASSERT_MALLOC(array->data);
|
LV_ASSERT_MALLOC(array->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lv_array_init_from_buf(lv_array_t * array, void * buf, uint32_t capacity, uint32_t element_size)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(buf);
|
||||||
|
array->size = 0;
|
||||||
|
array->capacity = capacity;
|
||||||
|
array->element_size = element_size;
|
||||||
|
|
||||||
|
array->data = buf;
|
||||||
|
array->inner_alloc = false;
|
||||||
|
}
|
||||||
|
|
||||||
void lv_array_deinit(lv_array_t * array)
|
void lv_array_deinit(lv_array_t * array)
|
||||||
{
|
{
|
||||||
if(array->data) {
|
if(array->data) {
|
||||||
lv_free(array->data);
|
if(array->inner_alloc) lv_free(array->data);
|
||||||
array->data = NULL;
|
array->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,15 +134,24 @@ lv_result_t lv_array_erase(lv_array_t * array, uint32_t start, uint32_t end)
|
|||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv_array_resize(lv_array_t * array, uint32_t new_capacity)
|
bool lv_array_resize(lv_array_t * array, uint32_t new_capacity)
|
||||||
{
|
{
|
||||||
|
if(array->inner_alloc == false) {
|
||||||
|
LV_LOG_WARN("Cannot resize array with external buffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t * data = lv_realloc(array->data, new_capacity * array->element_size);
|
uint8_t * data = lv_realloc(array->data, new_capacity * array->element_size);
|
||||||
LV_ASSERT_NULL(data);
|
LV_ASSERT_NULL(data);
|
||||||
|
|
||||||
|
if(data == NULL) return false;
|
||||||
|
|
||||||
array->data = data;
|
array->data = data;
|
||||||
array->capacity = new_capacity;
|
array->capacity = new_capacity;
|
||||||
if(array->size > new_capacity) {
|
if(array->size > new_capacity) {
|
||||||
array->size = new_capacity;
|
array->size = new_capacity;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other)
|
lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other)
|
||||||
@@ -139,7 +160,9 @@ lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other)
|
|||||||
uint32_t size = other->size;
|
uint32_t size = other->size;
|
||||||
if(array->size + size > array->capacity) {
|
if(array->size + size > array->capacity) {
|
||||||
/*array is full*/
|
/*array is full*/
|
||||||
lv_array_resize(array, array->size + size);
|
if(lv_array_resize(array, array->size + size) == false) {
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * data = array->data + array->size * array->element_size;
|
uint8_t * data = array->data + array->size * array->element_size;
|
||||||
@@ -154,7 +177,9 @@ lv_result_t lv_array_push_back(lv_array_t * array, const void * element)
|
|||||||
|
|
||||||
if(array->size == array->capacity) {
|
if(array->size == array->capacity) {
|
||||||
/*array is full*/
|
/*array is full*/
|
||||||
lv_array_resize(array, array->capacity + LV_ARRAY_DEFAULT_CAPACITY);
|
if(lv_array_resize(array, array->capacity + LV_ARRAY_DEFAULT_CAPACITY) == false) {
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ struct _lv_array_t {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
uint32_t element_size;
|
uint32_t element_size;
|
||||||
|
|
||||||
|
bool inner_alloc; /* true: data is allocated by the array; false: data is allocated by the user */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@@ -51,13 +53,24 @@ struct _lv_array_t {
|
|||||||
*/
|
*/
|
||||||
void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size);
|
void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init an array from a buffer.
|
||||||
|
* @note The buffer must be large enough to store `capacity` elements. The array will not release the buffer and reallocate it.
|
||||||
|
* The user must ensure that the buffer is valid during the lifetime of the array. And release the buffer when the array is no longer needed.
|
||||||
|
* @param array pointer to an `lv_array_t` variable to initialize
|
||||||
|
* @param buf pointer to a buffer to use as the array's data
|
||||||
|
* @param capacity the initial capacity of the array
|
||||||
|
* @param element_size the size of an element in bytes
|
||||||
|
*/
|
||||||
|
void lv_array_init_from_buf(lv_array_t * array, void * buf, uint32_t capacity, uint32_t element_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize the array to the given capacity.
|
* Resize the array to the given capacity.
|
||||||
* @note if the new capacity is smaller than the current size, the array will be truncated.
|
* @note if the new capacity is smaller than the current size, the array will be truncated.
|
||||||
* @param array pointer to an `lv_array_t` variable
|
* @param array pointer to an `lv_array_t` variable
|
||||||
* @param new_capacity the new capacity of the array
|
* @param new_capacity the new capacity of the array
|
||||||
*/
|
*/
|
||||||
void lv_array_resize(lv_array_t * array, uint32_t new_capacity);
|
bool lv_array_resize(lv_array_t * array, uint32_t new_capacity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deinit the array, and free the allocated memory
|
* Deinit the array, and free the allocated memory
|
||||||
|
|||||||
296
src/misc/lv_circle_buf.c
Normal file
296
src/misc/lv_circle_buf.c
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
lv_array_clear(&circle_buf->array);
|
||||||
|
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);
|
||||||
|
}
|
||||||
191
src/misc/lv_circle_buf.h
Normal file
191
src/misc/lv_circle_buf.h
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_circle_buf.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LV_CIRCLE_BUF_H
|
||||||
|
#define LV_CIRCLE_BUF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_types.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
typedef bool (*lv_circle_buf_fill_cb_t)(void * buf, uint32_t buff_len, int32_t index, void * user_data);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a circle buffer
|
||||||
|
* @param capacity the maximum number of elements in the buffer
|
||||||
|
* @param element_size the size of an element in bytes
|
||||||
|
* @return pointer to the created buffer
|
||||||
|
*/
|
||||||
|
lv_circle_buf_t * lv_circle_buf_create(uint32_t capacity, uint32_t element_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a circle buffer from an existing buffer
|
||||||
|
* @param buf pointer to a buffer
|
||||||
|
* @param capacity the maximum number of elements in the buffer
|
||||||
|
* @param element_size the size of an element in bytes
|
||||||
|
* @return pointer to the created buffer
|
||||||
|
*/
|
||||||
|
lv_circle_buf_t * lv_circle_buf_create_from_buf(void * buf, uint32_t capacity, uint32_t element_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a circle buffer from an existing array
|
||||||
|
* @param array pointer to an array
|
||||||
|
* @return pointer to the created buffer
|
||||||
|
*/
|
||||||
|
lv_circle_buf_t * lv_circle_buf_create_from_array(const lv_array_t * array);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the buffer
|
||||||
|
* @param circle_buf pointer to a buffer
|
||||||
|
* @param capacity the new capacity of the buffer
|
||||||
|
* @return LV_RESULT_OK: the buffer is resized; LV_RESULT_INVALID: the buffer is not resized
|
||||||
|
*/
|
||||||
|
lv_result_t lv_circle_buf_resize(lv_circle_buf_t * circle_buf, uint32_t capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a circle buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
*/
|
||||||
|
void lv_circle_buf_destroy(lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of the buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return the number of elements in the buffer
|
||||||
|
*/
|
||||||
|
uint32_t lv_circle_buf_size(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the capacity of the buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return the maximum number of elements in the buffer
|
||||||
|
*/
|
||||||
|
uint32_t lv_circle_buf_capacity(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remaining space in the buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return the number of elements that can be written to the buffer
|
||||||
|
*/
|
||||||
|
uint32_t lv_circle_buf_remain(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the buffer is empty
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return true: the buffer is empty; false: the buffer is not empty
|
||||||
|
*/
|
||||||
|
bool lv_circle_buf_is_empty(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the buffer is full
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return true: the buffer is full; false: the buffer is not full
|
||||||
|
*/
|
||||||
|
bool lv_circle_buf_is_full(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return LV_RESULT_OK: the buffer is reset; LV_RESULT_INVALID: the buffer is not reset
|
||||||
|
*/
|
||||||
|
void lv_circle_buf_reset(lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the head of the buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return pointer to the head of the buffer
|
||||||
|
*/
|
||||||
|
void * lv_circle_buf_head(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tail of the buffer
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return pointer to the tail of the buffer
|
||||||
|
*/
|
||||||
|
void * lv_circle_buf_tail(const lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a value
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @param data pointer to a variable to store the read value
|
||||||
|
* @return LV_RESULT_OK: the value is read; LV_RESULT_INVALID: the value is not read
|
||||||
|
*/
|
||||||
|
lv_result_t lv_circle_buf_read(lv_circle_buf_t * circle_buf, void * data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a value
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @param data pointer to the value to write
|
||||||
|
* @return LV_RESULT_OK: the value is written; LV_RESULT_INVALID: the value is not written
|
||||||
|
*/
|
||||||
|
lv_result_t lv_circle_buf_write(lv_circle_buf_t * circle_buf, const void * data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the buffer with values
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @param count the number of values to fill
|
||||||
|
* @param fill_cb the callback function to fill the buffer
|
||||||
|
* @param user_data
|
||||||
|
* @return the number of values filled
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip a value
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @return LV_RESULT_OK: the value is skipped; LV_RESULT_INVALID: the value is not skipped
|
||||||
|
*/
|
||||||
|
lv_result_t lv_circle_buf_skip(lv_circle_buf_t * circle_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek a value
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @param data pointer to a variable to store the peeked value
|
||||||
|
* @return LV_RESULT_OK: the value is peeked; LV_RESULT_INVALID: the value is not peeked
|
||||||
|
*/
|
||||||
|
lv_result_t lv_circle_buf_peek(const lv_circle_buf_t * circle_buf, void * data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek a value at an index
|
||||||
|
* @param circle_buf pointer to buffer
|
||||||
|
* @param index the index of the value to peek, if the index is greater than the size of the buffer, it will return looply.
|
||||||
|
* @param data pointer to a variable to store the peeked value
|
||||||
|
* @return LV_RESULT_OK: the value is peeked; LV_RESULT_INVALID: the value is not peeked
|
||||||
|
*/
|
||||||
|
lv_result_t lv_circle_buf_peek_at(const lv_circle_buf_t * circle_buf, uint32_t index, void * data);
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
* GLOBAL VARIABLES
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_CIRCLE_BUF_H*/
|
||||||
@@ -326,6 +326,8 @@ typedef struct _lv_array_t lv_array_t;
|
|||||||
|
|
||||||
typedef struct _lv_iter_t lv_iter_t;
|
typedef struct _lv_iter_t lv_iter_t;
|
||||||
|
|
||||||
|
typedef struct _lv_circle_buf_t lv_circle_buf_t;
|
||||||
|
|
||||||
typedef struct _lv_draw_buf_t lv_draw_buf_t;
|
typedef struct _lv_draw_buf_t lv_draw_buf_t;
|
||||||
|
|
||||||
#if LV_USE_OBJ_PROPERTY
|
#if LV_USE_OBJ_PROPERTY
|
||||||
|
|||||||
167
tests/src/test_cases/test_circle_buf.c
Normal file
167
tests/src/test_cases/test_circle_buf.c
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#if LV_BUILD_TEST
|
||||||
|
#include "../lvgl.h"
|
||||||
|
#include "../../lvgl_private.h"
|
||||||
|
|
||||||
|
#include "unity/unity.h"
|
||||||
|
|
||||||
|
static lv_circle_buf_t * circle_buf;
|
||||||
|
|
||||||
|
#define circle_buf_CAPACITY 4
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
circle_buf = lv_circle_buf_create(circle_buf_CAPACITY, sizeof(int32_t));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_capacity(circle_buf), circle_buf_CAPACITY);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0, lv_circle_buf_size(circle_buf));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write values to the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||||
|
* When the buffer is full, the write operation should return LV_RESULT_INVALID.
|
||||||
|
*/
|
||||||
|
for(int32_t i = 0; i < circle_buf_CAPACITY * 2; i++) {
|
||||||
|
const lv_result_t res = lv_circle_buf_write(circle_buf, &i);
|
||||||
|
|
||||||
|
if(i < circle_buf_CAPACITY) TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
else TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After writing values to the buffer, the size of the buffer should be equal to the capacity.
|
||||||
|
*/
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_size(circle_buf), circle_buf_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
lv_circle_buf_destroy(circle_buf);
|
||||||
|
circle_buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_circle_buf_read_write_peek_values(void)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read 1 value from the buffer.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int32_t value;
|
||||||
|
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL_INT32(0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek values will not advance the read and write cursors.
|
||||||
|
* If the peek index is greater than the size of the buffer, it will returns looply.
|
||||||
|
*/
|
||||||
|
for(int32_t i = 0, j = 1; i < circle_buf_CAPACITY * 10; i++, j++) {
|
||||||
|
int32_t value;
|
||||||
|
const lv_result_t res = lv_circle_buf_peek_at(circle_buf, i, &value);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL_INT32(j, value);
|
||||||
|
|
||||||
|
if(j == 3) j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||||
|
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
|
||||||
|
*/
|
||||||
|
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
|
||||||
|
int32_t value;
|
||||||
|
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||||
|
|
||||||
|
if(i < circle_buf_CAPACITY) {
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL_INT32(i, value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After reading values from the buffer, the size of the buffer should be equal to 0.
|
||||||
|
*/
|
||||||
|
TEST_ASSERT_EQUAL_INT32(0, lv_circle_buf_size(circle_buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_circle_buf_skip_values(void)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Skip 1 value from the buffer.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const lv_result_t res = lv_circle_buf_skip(circle_buf);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||||
|
* When the buffer is empty, the skip operation should return LV_RESULT_INVALID.
|
||||||
|
*/
|
||||||
|
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
|
||||||
|
const lv_result_t res = lv_circle_buf_skip(circle_buf);
|
||||||
|
|
||||||
|
if(i < circle_buf_CAPACITY) {
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After skipping values from the buffer, the size of the buffer should be equal to 0.
|
||||||
|
*/
|
||||||
|
TEST_ASSERT_EQUAL_INT32(0, lv_circle_buf_size(circle_buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_circle_buf_read_after_read_and_write(void)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read 1 value from the buffer.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int32_t value;
|
||||||
|
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL_INT32(0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write 1 value to the buffer.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const int32_t value = 4;
|
||||||
|
const lv_result_t res = lv_circle_buf_write(circle_buf, &value);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32_t expected[] = {4, 1, 2, 3};
|
||||||
|
TEST_ASSERT_EQUAL_INT32_ARRAY(expected, ((lv_array_t *)circle_buf)->data, 4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||||
|
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
|
||||||
|
*/
|
||||||
|
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
|
||||||
|
int32_t value;
|
||||||
|
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||||
|
|
||||||
|
if(i <= circle_buf_CAPACITY) {
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL_INT32(i, value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user