Appiko
Macros
CBUF.h File Reference

This file contains global definitions for circular buffer manipulation. More...

Go to the source code of this file.

Macros

#define CBUF_H
 
#define CBUF_Init(cbuf)   cbuf.m_getIdx = cbuf.m_putIdx = 0
 
#define CBUF_Len(cbuf)   ((typeof( cbuf.m_putIdx ))(( cbuf.m_putIdx ) - ( cbuf.m_getIdx )))
 
#define CBUF_Push(cbuf, elem)   (cbuf.m_entry)[ cbuf.m_putIdx++ & (( cbuf##_SIZE ) - 1 )] = (elem)
 
#define CBUF_Pop(cbuf)   (cbuf.m_entry)[ cbuf.m_getIdx++ & (( cbuf##_SIZE ) - 1 )]
 
#define CBUF_Get(cbuf, idx)   (cbuf.m_entry)[( cbuf.m_getIdx + idx ) & (( cbuf##_SIZE ) - 1 )]
 
#define CBUF_GetEnd(cbuf, idx)   (cbuf.m_entry)[( cbuf.m_putIdx - idx - 1 ) & (( cbuf##_SIZE ) - 1 )]
 
#define CBUF_IsEmpty(cbuf)   ( CBUF_Len( cbuf ) == 0 )
 
#define CBUF_IsFull(cbuf)   ( CBUF_Len( cbuf ) == ( cbuf##_SIZE ))
 
#define CBUF_Error(cbuf)   ( CBUF_Len( cbuf ) > cbuf##_SIZE )
 
#define CBUF_GetPtr(cbuf, idx)   ((typeof( &cbuf.m_entry[0]))( cbuf.m_entry + (( cbuf.m_getIdx + idx ) & (( cbuf##_SIZE ) - 1 ))))
 
#define CBUF_Remove(cbuf, idx)   ({cbuf.m_getIdx += ( idx );})
 

Detailed Description

These macros implement a circular buffer which employs get and put pointers, in such a way that mutual exclusion is not required (assumes one reader & one writer).

It requires that the circular buffer size be a power of two, and the size of the buffer needs to smaller than the index. So an 8 bit index supports a circular buffer upto ( 1 << 7 ) = 128 entries, and a 16 bit index supports a circular buffer upto ( 1 << 15 ) = 32768 entries.

The basis for these routines came from an article in Jack Ganssle's Embedded Muse: http://www.ganssle.com/tem/tem110.pdf

In order to offer the most amount of flexibility for embedded environments you need to define a macro for the size.

First, you need to name your circular buffer. For this example, we'll call it myQ.

The size macro that needs to be defined will be the name of the circular buffer followed by _SIZE. The size must be a power of two and it needs to fit in the get/put indicies. i.e. if you use an 8 bit index, then the maximum supported size would be 128.

The structure which defines the circular buffer needs to have 3 members m_getIdx, m_putIdx, and m_entry.

m_getIdx and m_putIdx need to be unsigned integers of the same size.

m_entry needs to be an array of xxx_SIZE entries, or a pointer to an array of xxx_SIZE entries. The type of each entry is entirely up to the caller.

#define myQ_SIZE 64

volatile struct { uint8_t m_getIdx; uint8_t m_putIdx; uint8_t m_entry[ myQ_SIZE ];

} myQ;

You could then use

CBUF_Push( myQ, 'x' );

to add a character to the circular buffer, or

ch = CBUF_Pop( myQ );

to retrieve an element from the buffer.

If you happen to prefer to use C++ instead, there is a templatized version which requires no macros. You just declare 3 template parameters:

- The type that should be used for the index
- The size of the circular buffer
- The type that should be used for the entry

For example:

CBUF< uint8_t, 64, char >   myQ;

Definition in file CBUF.h.

Macro Definition Documentation

◆ CBUF_Error

#define CBUF_Error (   cbuf)    ( CBUF_Len( cbuf ) > cbuf##_SIZE )

Determines if the circular buffer is currently overflowed or underflowed.

Definition at line 139 of file CBUF.h.

◆ CBUF_Get

#define CBUF_Get (   cbuf,
  idx 
)    (cbuf.m_entry)[( cbuf.m_getIdx + idx ) & (( cbuf##_SIZE ) - 1 )]

Retrieves the i'th element from the beginning of the circular buffer

Definition at line 115 of file CBUF.h.

◆ CBUF_GetEnd

#define CBUF_GetEnd (   cbuf,
  idx 
)    (cbuf.m_entry)[( cbuf.m_putIdx - idx - 1 ) & (( cbuf##_SIZE ) - 1 )]

Retrieves the i'th element from the end of the circular buffer

Definition at line 121 of file CBUF.h.

◆ CBUF_GetPtr

#define CBUF_GetPtr (   cbuf,
  idx 
)    ((typeof( &cbuf.m_entry[0]))( cbuf.m_entry + (( cbuf.m_getIdx + idx ) & (( cbuf##_SIZE ) - 1 ))))

Retrieves the pointer element to be popped incremented by an offset

Definition at line 145 of file CBUF.h.

◆ CBUF_H

#define CBUF_H

Include Guard

Definition at line 80 of file CBUF.h.

◆ CBUF_Init

#define CBUF_Init (   cbuf)    cbuf.m_getIdx = cbuf.m_putIdx = 0

Initializes the circular buffer for use.

Definition at line 90 of file CBUF.h.

◆ CBUF_IsEmpty

#define CBUF_IsEmpty (   cbuf)    ( CBUF_Len( cbuf ) == 0 )

Determines if the circular buffer is empty

Definition at line 127 of file CBUF.h.

◆ CBUF_IsFull

#define CBUF_IsFull (   cbuf)    ( CBUF_Len( cbuf ) == ( cbuf##_SIZE ))

Determines if the circular buffer is full.

Definition at line 133 of file CBUF.h.

◆ CBUF_Len

#define CBUF_Len (   cbuf)    ((typeof( cbuf.m_putIdx ))(( cbuf.m_putIdx ) - ( cbuf.m_getIdx )))

Returns the number of elements which are currently contained in the circular buffer.

Definition at line 97 of file CBUF.h.

◆ CBUF_Pop

#define CBUF_Pop (   cbuf)    (cbuf.m_entry)[ cbuf.m_getIdx++ & (( cbuf##_SIZE ) - 1 )]

Retrieves an element from the beginning of the circular buffer

Definition at line 109 of file CBUF.h.

◆ CBUF_Push

#define CBUF_Push (   cbuf,
  elem 
)    (cbuf.m_entry)[ cbuf.m_putIdx++ & (( cbuf##_SIZE ) - 1 )] = (elem)

Appends an element to the end of the circular buffer

Definition at line 103 of file CBUF.h.

◆ CBUF_Remove

#define CBUF_Remove (   cbuf,
  idx 
)    ({cbuf.m_getIdx += ( idx );})

Removes (like popping) a specified number of elements from the buffer

Definition at line 151 of file CBUF.h.