108 lines
3.1 KiB
C
108 lines
3.1 KiB
C
/*
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @brief Generic double buffer data structure header.
|
|
*
|
|
* The structure may be used as a header for any kind of data structure that requires
|
|
* double buffering.
|
|
*/
|
|
struct dbuf_hdr {
|
|
/* The current element that is in use. */
|
|
uint8_t volatile first;
|
|
/* Last enqueued element. It will be used after buffer is swapped. */
|
|
uint8_t last;
|
|
/* Size in a bytes of a single element stored in double buffer. */
|
|
uint8_t elem_size;
|
|
/* Pointer for actual buffer memory. Its size should be 2 times @p elem_size. */
|
|
uint8_t data[0];
|
|
};
|
|
|
|
/**
|
|
* @brief Allocate element in double buffer.
|
|
*
|
|
* The function provides pointer to new element that may be modified by the user.
|
|
* For consecutive calls it always returns the same pointer until buffer is swapped
|
|
* by dbuf_latest_get operation.
|
|
*
|
|
* @param hdr Pointer to double buffer header.
|
|
* @param idx Pointer to return new element index.
|
|
*
|
|
* @return Pointer to new element memory.
|
|
*/
|
|
void *dbuf_alloc(struct dbuf_hdr *hdr, uint8_t *idx);
|
|
|
|
/**
|
|
* @brief Provides pointer to last allocated element.
|
|
*
|
|
* If it is called before dbuf_alloc it will return pointer to memory that was recently
|
|
* enqueued.
|
|
*
|
|
* @param hdr Pointer to double buffer header.
|
|
*
|
|
* @return Pointer to last allocated element.
|
|
*/
|
|
static inline void *dbuf_peek(struct dbuf_hdr *hdr)
|
|
{
|
|
return &hdr->data[hdr->last * hdr->elem_size];
|
|
}
|
|
|
|
/**
|
|
* @brief Enqueue new element for buffer swap.
|
|
*
|
|
* @param hdr Pointer to double buffer header.
|
|
* @param idx Index of element to be swapped.
|
|
*/
|
|
static inline void dbuf_enqueue(struct dbuf_hdr *hdr, uint8_t idx)
|
|
{
|
|
hdr->last = idx;
|
|
}
|
|
|
|
/**
|
|
* @brief Get latest element in buffer.
|
|
*
|
|
* Latest enqueued element is pointed by last member of dbuf_hdr.
|
|
* If it points to a different index than member first, then buffer will be
|
|
* swapped and @p is_modified will be set to true.
|
|
*
|
|
* Pointer to latest element is returned.
|
|
*
|
|
* @param[in] hdr Pointer to double buffer header.
|
|
* @param[out] is_modified Pointer to return information if buffer was swapped.
|
|
*
|
|
* @return Pointer to latest enqueued buffer element.
|
|
*/
|
|
void *dbuf_latest_get(struct dbuf_hdr *hdr, uint8_t *is_modified);
|
|
|
|
/**
|
|
* @brief Returns pointer to the current element, the one after last swap operation.
|
|
*
|
|
* The function provides access to element that is pointed by member first of dbuf_hrd.
|
|
* Returned value always points to latest one, that was swapped after most recent call to
|
|
* dbuf_latest_get. The pointer will be the same as the one pointed by last if the dbuf_alloc
|
|
* is not called after last dbuf_latest_get call.
|
|
*
|
|
* @param hdr Pointer to double buffer header.
|
|
|
|
* @return Pointer to element after last buffer swap.
|
|
*/
|
|
static inline void *dbuf_curr_get(struct dbuf_hdr *hdr)
|
|
{
|
|
return &hdr->data[hdr->first * hdr->elem_size];
|
|
}
|
|
|
|
/**
|
|
* @brief Return information whether new element was enqueued to a buffer.
|
|
*
|
|
* @param hdr Pointer to double buffer header.
|
|
*
|
|
* @return True if there were new element enqueued, false in other case.
|
|
*/
|
|
static inline bool dbuf_is_modified(const struct dbuf_hdr *hdr)
|
|
{
|
|
return hdr->first != hdr->last;
|
|
}
|