bleSDK_expansion_board/modules/api/rbuf.h

262 lines
7.1 KiB
C
Raw Permalink Normal View History

/**
****************************************************************************************
*
* @file rbuf.h
*
* @brief Definitons of Ring Buffer module(Predefine Size, Byte-byte Copy).
*
****************************************************************************************
*/
#ifndef _RBUF_H_
#define _RBUF_H_
#include <stdint.h>
#include <stdbool.h>
/*
* DEFINES
****************************************************************************************
*/
/// Buffer space size *User should redefine it via #undef RBUF_SIZE.
#ifndef RBUF_SIZE
#define RBUF_SIZE 0x100
#endif
/// Length type of buffer
#ifndef rblen_t
#define rblen_t uint16_t
#endif
/// Macro of utils function
#define IS_PWR_2(n) ((n != 0) && ((n & (n - 1)) == 0))
#define RBUF_MIN(a, b) ((a) < (b) ? (a) : (b))
#define RBUF_MAX(a, b) ((a) > (b) ? (a) : (b))
#if IS_PWR_2(RBUF_SIZE)
// Increase 'p'(position) with 's'(step).
#define RBUF_INC(p, s) ((p + s) % RBUF_SIZE)
// Get number of bytes currently in buffer.
#define RBUF_LEN(h, t) ((RBUF_SIZE + h - t) % RBUF_SIZE)
// Get available size in buffer for write, 1 less than it actually is.
#define RBUF_AVAIL(h, t) ((RBUF_SIZE + t - h - 1) % RBUF_SIZE)
#else
// Increase 'p'(position) with 's'(step).
#define RBUF_INC(p, s) ((p == (RBUF_SIZE - s)) ? (s - 1) : (p + s))
// Get number of bytes currently in buffer.
#define RBUF_LEN(h, t) ((h >= t) ? (h - t) : (RBUF_SIZE + h - t))
// Get available size in buffer for write, 1 less than it actually is.
#define RBUF_AVAIL(h, t) ((t > h) ? (t - h - 1) : (RBUF_SIZE + t - h - 1))
#endif
/// Struct type of Ring Buffer
typedef struct ringbuffer
{
volatile rblen_t head;
volatile rblen_t tail;
uint8_t data[RBUF_SIZE];
} rbuf_t;
/*
* INLINE FUNCTION
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Init/Reset the entire BUFF contents.
*
* @param[in] rb The ringbuff to be emptied.
* @return None.
****************************************************************************************
*/
static __forceinline void rbuf_init(rbuf_t *rb)
{
rb->head = rb->tail = 0;
}
/**
****************************************************************************************
* @brief Returns the size of the BUFF in bytes.
*
* @param[in] rb The ringbuff to be used.
* @return The size of the BUFF.
****************************************************************************************
*/
static __forceinline rblen_t rbuf_size(rbuf_t *rb)
{
return RBUF_SIZE; // Direct return
}
/**
****************************************************************************************
* @brief Returns the number of used bytes in the BUFF.
*
* @param[in] rb The ringbuff to be used.
* @return The number of used bytes.
****************************************************************************************
*/
static __forceinline rblen_t rbuf_len(rbuf_t *rb)
{
rblen_t head = rb->head;
rblen_t tail = rb->tail;
return RBUF_LEN(head, tail);
}
/**
****************************************************************************************
* @brief Returns the number of bytes available in the BUFF.
*
* @param[in] rb The ringbuff to be used.
* @return The number of bytes available.
****************************************************************************************
*/
static __forceinline rblen_t rbuf_avail(rbuf_t *rb)
{
rblen_t head = rb->head;
rblen_t tail = rb->tail;
return RBUF_AVAIL(head, tail);
}
/**
****************************************************************************************
* @brief Is the BUFF empty?
*
* @param[in] rb The ringbuff to be used.
* @return Yes or No.
****************************************************************************************
*/
static __forceinline bool rbuf_is_empty(rbuf_t *rb)
{
return (rb->head == rb->tail);
}
/**
****************************************************************************************
* @brief Is the BUFF full?
*
* @param[in] rb The ringbuff to be used.
* @return Yes or No.
****************************************************************************************
*/
static __forceinline bool rbuf_is_full(rbuf_t *rb)
{
rblen_t head = rb->head;
rblen_t tail = rb->tail;
return (RBUF_AVAIL(head, tail) == 0);
}
/**
****************************************************************************************
* @brief Force Put one byte into the BUFF.
*
* @param[in] rb The ringbuff to be used.
* @param[in] ch The byte to be added.
*
* @return None.
****************************************************************************************
*/
static __forceinline void rbuf_putc(rbuf_t *rb, uint8_t ch)
{
rblen_t head = rb->head;
rb->data[head] = ch;
rb->head = RBUF_INC(head, 1);
}
/**
****************************************************************************************
* @brief Force Puts some data into the BUFF.
*
* @param[in] rb The ringbuff to be used.
* @param[in] in The data to be added.
* @param[in] len The length of the data to be added.
*
* @return None.
****************************************************************************************
*/
static __forceinline void rbuf_puts(rbuf_t *rb, const uint8_t *in, rblen_t len)
{
rblen_t head = rb->head;
// copy byte to byte
for (rblen_t i = 0; i < len; i++)
{
rb->data[head] = in[i];
head = RBUF_INC(head, 1);
}
rb->head = head;
}
/**
****************************************************************************************
* @brief Get one byte from the BUFF.
*
* @param[in] rb The ringbuff to be used.
* @param[out] ch Where the byte be copied.
*
* @return Byte copied or not.
****************************************************************************************
*/
static __forceinline bool rbuf_getc(rbuf_t *rb, uint8_t *ch)
{
rblen_t head = rb->head;
rblen_t tail = rb->tail;
if (head != tail)
{
*ch = rb->data[tail];
rb->tail = RBUF_INC(tail, 1);
return 1;
}
return 0; // empty
}
/**
****************************************************************************************
* @brief Gets some data from the BUFF.
*
* @param[in] rb The ringbuff to be used.
* @param[out] out Where the data must be copied.
* @param[in] max The max size of the destination buffer.
*
* @return The number of copied bytes.
****************************************************************************************
*/
static __forceinline rblen_t rbuf_gets(rbuf_t *rb, uint8_t *out, rblen_t max)
{
rblen_t head = rb->head;
rblen_t tail = rb->tail;
rblen_t dlen = RBUF_LEN(head, tail);
if (dlen > max)
{
dlen = max;
}
if (dlen > 0)
{
// copy byte to byte
for (rblen_t i = 0; i < dlen; i++)
{
out[i] = rb->data[tail];
tail = RBUF_INC(tail, 1);
}
rb->tail = tail;
}
return dlen;
}
#endif // _RBUF_H_