Multi purpose buffer module.

Multipurpose ringbuffer

Since there weren't any ringbuffers available on the internet optimized for 32-Bit ARM operation without unix-calls and dynamic memory... I created one.

This module is a fixed ringbuffer, it does not allocate any memory, it can work as FIFO or LIFO or any other exotic mode depending on your imagination. With a fixed 32Bit element size it is optimized for 32 bit arm processors. Any smaller value will have overhead, any larger value will require a double entry. (not recommended)

I hope you can use it.

Information

This is not a C++ class, it is a C Module. It does work object oriented, however you cannot work on the object, you work with the object.

Import programxIFO_example

Small example for xIFO

xIFO.h

Committer:
jeroen3
Date:
2014-04-04
Revision:
2:6013f6d867e5
Parent:
0:a04dc0c57d20

File content as of revision 2:6013f6d867e5:

/**
 * @file    xifo.h
 * @brief   xifo circular buffer for all elements
 * @details xifo supplies object oriented circular buffer with x bit size elements. \n
 *          To use either as FIFO (First In First Out) or as FILO (First In Last Out)
 *          Below are defines to disable or enable any xIFO type you like.
 *
 * @author  Jeroen Lodder
 * @date    March 2014
 * @version 3
 * 
 * Copyright (c) 2014 Jeroen Lodder
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * @{
 */
#ifndef _xifo_H_
#define _xifo_H_
 
#include <inttypes.h>

#if !defined(TRUE) || defined(__DOXYGEN__)
#define TRUE    (1)
#endif
#if !defined(FALSE) || defined(__DOXYGEN__)
#define FALSE   !(TRUE)
#endif
 
#ifdef __cplusplus
#if !defined(xIFO_USE_CPP) || defined(__DOXYGEN__)
#define xIFO_USE_CPP            TRUE
#endif
#endif

#if !defined(xIFO_USE_64BIT) || defined(__DOXYGEN__)
#define xIFO_USE_64BIT          TRUE
#endif

#if !defined(xIFO_USE_32BIT) || defined(__DOXYGEN__)
#define xIFO_USE_32BIT          TRUE
#endif

#if !defined(xIFO_USE_16BIT) || defined(__DOXYGEN__)
#define xIFO_USE_16BIT          TRUE
#endif

#if !defined(xIFO_USE_8BIT) || defined(__DOXYGEN__)
#define xIFO_USE_8BIT           TRUE
#endif


#if xIFO_USE_CPP == TRUE
/**
 * @brief   Circular Buffer object.
 * @details This class holds the object of a circular buffer
 */
template <class xifo_dtype>
class Xifo
{
public:
    /**
     * @brief   Initialise xifo.
     * @note    Does not clear memory pool.
     * @param[in] Number of elements buffer can hold (size).
     */
    Xifo(uint32_t size)
    {
        startpool = new xifo_dtype[size];
        endpool         = &startpool[size-1];
        isize           = size;
        ifull           = 0;
        icount           = 0;
        read            = startpool;
        pwrite          = startpool;
    }

    /**
     * @brief   Initialise xifo.
     * @note    Does not clear memory pool.
     * @param[in] Number of elements buffer can hold (size).
     * @param[in] Start of pre-allocated memory pool.
     */
    Xifo(uint32_t size, xifo_dtype *sp)
    {
        startpool       = sp;
        endpool         = &sp[size-1];
        isize           = size;
        ifull           = 0;
        icount            = 0;
        read            = sp;
        pwrite          = sp;
    }

    /**
     * @brief   Deinitialise (and deallocate) buffer xifo.
     * @note    Does not clear memory pool.
     */
    ~Xifo(void)
    {
        if(dynamic){
            delete startpool;
        }
    }

    /**
     * @brief   Clear buffer memory pool
     * @note    Must be used on initialised buffer object.
     * @param[in] c   Pointer to @p xifo_SIZETYPE_t object.
     */
    void clear(void)
    {
        register xifo_dtype *ptemp = startpool;
        while(ptemp <= endpool){
            *ptemp++ = 0;
        }
    }
    
     /**
     * @brief   Reset buffer
     * @note    Must be used on initialised buffer object.
     * @param[in] c   Pointer to @p xifo_SIZETYPE_t object.
     */
    void reset(void)
    {
        register xifo_dtype *ptemp = startpool;
        while(ptemp <= endpool){
            *ptemp++ = 0;
        }
        ifull       = 0;
        icount      = 0;
        read        = startpool;
        pwrite      = startpool;
    }

    /**
     * @brief   Write to buffer
     *
     * @note    Readpointer is automatically set to the last added element.
     *
     * @warning Consider this opertaion as atomic!
     *
     * @details Adds a value to the buffer.
     *                  Automatically overwrites oldest elements when full.
     *
     * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
     * @param[in] data  Data to add to buffer
     *
     * @return  Number of free buffer elements
     */
    uint32_t write(xifo_dtype data)
    {
        /* Write data */
        *pwrite = data;
        /* Update read pointer to most recent element */
        read = pwrite;
        /* Write pointer increment */
        pwrite += 1;
        /* Validate pointer */
        if( pwrite > endpool){
            /* Exceeded pool boundaries */
            pwrite = startpool;
        }
        /* Update count */
        icount++;
        /* Verify full */
        if( icount >= isize ){
            ifull = 1;
            icount = isize;
        }
        /* return free elements count */
        return isize - icount;
    }

    /**
     * @brief   Read from buffer (lr) Least Recent oriented (fifo)
     *
     * @note    Buffer state will be preserved
     *
     * @warning Consider this opertaion as atomic!
     *
     * @details Read n elements from the oldest element to the most recent.
     *                  As for index[0] the least recently added element is returned.
     *                  And for index[count] the most recent element is returned.
     *                  This makes it possible to peek in fifo.
     *
     * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
     * @param[in] index   Index relative from least recent
     *
     * @return  Contents of element or 0 if failed (element can hold 0)
     */
    xifo_dtype read_lr(uint32_t index)
    {
        register xifo_dtype *ptemp;
        /* Verify there is valid data to read */
        if(index+1 > icount){
            return 0;
        }
        /* Calculate index of oldest element */
        index = (icount-1) - index;
        /* Set pointer */
        ptemp = (read) - index;
        if(ptemp < startpool){
            /* Exceeded pool boundaries */
            /* Calculate overshoot (startpool - indexptr) and subtract from end */
            /* Since one element of overshoot results in end - 1 you would miss the last value */
            ptemp = (endpool+1) - (startpool - ptemp);
        }
        /* Read most recent */
        return *ptemp;
    }

    /**
     * @brief   Pop (lr) least recent from buffer (fifo)
     *
     * @note    Buffer state will be altered
     *
     * @warning Consider this opertaion as atomic!
     *
     * @details Read and remove the least recently added from the buffer.
     *                  Using this results in a fifo type of buffer.
     *
     * @param[in] c Pointer to @p xifo_SIZETYPE_t used for configuration.
     *
     * @return  Contents of element or 0 if failed (element can hold 0)
     */
    xifo_dtype pop_lr()
    {
        register xifo_dtype *ptemp;
        xifo_dtype temp;
        /* Verify there is valid data read */
        if(icount == 0){
            return 0;
        }
        /* Derive least recent buffer element */
        ptemp = read+1 - icount;
        /* Validate pointer */
        if(ptemp < startpool){
            /* Exceeded pool boundaries */
            /* Calculate overshoot (startpool - indexptr) and subtract from end */
            /* Since one element of overshoot results in end - 1 you would miss the last value */
            ptemp = (endpool+1) - (startpool - ptemp);
        }
        /* Read oldest buffer element */
        /* Read to temp register */
        temp = *ptemp;
        /* Empty buffer element */
        *ptemp = 0;
        /* Reduce count */
        icount--;
        /* Check full flag */
        if(icount < isize)
            ifull = 0;
        return temp;
    }

    /**
     * @brief   Read from buffer (mr) Most Recent oriented (filo)
     *
     * @note    Buffer state will be preserved
     *
     * @warning Consider this opertaion as atomic!
     *
     * @details Read n elements back in time.
     *                  As for index[0] the most recently added element is returned.
     *                  And for index[count] the oldest element is returned.
     *                  This makes it possible to keep history. For DSP application.
     *
     * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
     * @param[in] index   Index relative from most recent
     *
     * @return  Contents of element or 0 if failed (element can hold 0)
     */
    xifo_dtype read_mr(uint32_t index)
    {
        register xifo_dtype *ptemp;
        /* Verify there is valid data to read */
        if(index+1 > icount){
            return 0;
        }
        /* Set pointer */
        ptemp = read - index;
        /* Validate pointer */
        if(ptemp < startpool){
            /* Exceeded pool boundaries */
            /* Calculate overshoot (startpool - indexptr) and subtract from end */
            /* Since one element of overshoot results in end - 1 you would miss the last value */
            ptemp = (endpool+1) - (startpool - ptemp);
        }
        /* Read most recent */
        return *ptemp;
    }

    /**
     * @brief   Pop (mr) most recent from buffer (filo)
     *
     * @note    Buffer state will be altered
     *
     * @warning Consider this opertaion as atomic!
     *
     * @details Read and remove the most recently added from the buffer.
     *                  Using this results in a stack type of buffer.
     *
     * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
     *
     * @return  Contents of element or 0 if failed (element can hold 0)
     */
    xifo_dtype pop_mr()
    {
        register xifo_dtype temp;
        /* Verify there is valid data read */
        if(icount == 0){
            return 0;
        }
        /* Read */
        temp = *read;
        /* Empty */
        *read = 0;
        /* Most recent element read, return write pointer */
        pwrite = read;
        /* Decrement read pointer */
        read--;
        /* Validate pointer */
        if( read < startpool ){
            /* Exceeded pool boundaries */
            read = endpool;
        }
        /* Reduce count */
        icount--;
        if(icount < isize)
            ifull = 0;
        return temp;
    }

    /* Extractors */
    uint32_t size(){ return isize; }         /**< @brief   Get buffer size */
    uint32_t used(){ return icount; }        /**< @brief   Get number of used elements */
    uint32_t full(){ return ifull; }         /**< @brief   Get full flag */
    uint32_t free(){ return isize-icount; }   /**< @brief   Get number of free elements */
private:
    bool dynamic;
    xifo_dtype *startpool;         /**< @brief First element in pool */
    xifo_dtype *endpool;    /**< @brief Last element in pool */
    xifo_dtype *read;       /**< @brief Read pointer */
    xifo_dtype *pwrite;     /**< @brief Write pointer */
    /* Variables: */
    uint32_t ifull;          /**< @brief Flag indicating buffer is full */
    uint32_t icount;         /**< @brief Number of elements used */
    uint32_t isize;          /**< @brief Size of buffer */
};
#endif

#if xIFO_USE_64BIT == TRUE
/**
 * @brief   Circular Buffer object.
 * @details This struct holds the object of a circular buffer
 */
typedef struct  {
    /* Pointers: */
    uint64_t *startpool;    /**< @brief First element in pool */
    uint64_t *endpool;      /**< @brief Last element in pool */
    uint64_t *read;         /**< @brief Read pointer */
    uint64_t *write;        /**< @brief Write pointer */
    /* Variables: */
    uint32_t full;          /**< @brief Flag indicating buffer is full */
    uint32_t count;         /**< @brief Number of elements used */
    uint32_t size;          /**< @brief Size of buffer */
}xifo64_t;

/**< @brief   Circular Buffer memory pool type. */
typedef uint64_t xifo64_pool_t;

#ifdef __cplusplus
extern "C" {
#endif
/* xifo Common */
void xifo64_init( xifo64_t *c, uint32_t size, uint64_t *startpool );
void xifo64_clear( xifo64_t *c );
uint32_t xifo64_write( xifo64_t *c, uint64_t data );
/* FIFO use */
uint64_t xifo64_read_lr( xifo64_t *c, uint32_t index );
uint64_t xifo64_pop_lr( xifo64_t *c );
/* LIFO use */
uint64_t xifo64_read_mr( xifo64_t *c, uint32_t index );
uint64_t xifo64_pop_mr( xifo64_t *c );
/* Extractors */
uint32_t xifo64_get_size( xifo64_t *c );
uint32_t xifo64_get_used( xifo64_t *c );
uint32_t xifo64_get_full( xifo64_t *c );
uint32_t xifo64_get_free( xifo64_t *c );
#ifdef __cplusplus
}
#endif
#endif

#if xIFO_USE_32BIT == TRUE
/**
 * @brief   Circular Buffer object.
 * @details This struct holds the object of a circular buffer
 */
typedef struct  {
    /* Pointers: */
    uint32_t *startpool;    /**< @brief First element in pool */
    uint32_t *endpool;      /**< @brief Last element in pool */
    uint32_t *read;         /**< @brief Read pointer */
    uint32_t *write;        /**< @brief Write pointer */
    /* Variables: */
    uint32_t full;          /**< @brief Flag indicating buffer is full */
    uint32_t count;         /**< @brief Number of elements used */
    uint32_t size;          /**< @brief Size of buffer */
}xifo32_t;

/**< @brief   Circular Buffer memory pool type. */
typedef uint32_t xifo32_pool_t;

#ifdef __cplusplus
extern "C" {
#endif
/* xifo Common */
void xifo32_init( xifo32_t *c, uint32_t size, uint32_t *startpool );
void xifo32_clear( xifo32_t *c );
uint32_t xifo32_write( xifo32_t *c, uint32_t data );
/* FIFO use */
uint32_t xifo32_read_lr( xifo32_t *c, uint32_t index );
uint32_t xifo32_pop_lr( xifo32_t *c );
/* LIFO use */
uint32_t xifo32_read_mr( xifo32_t *c, uint32_t index );
uint32_t xifo32_pop_mr( xifo32_t *c );
/* Extractors */
uint32_t xifo32_get_size( xifo32_t *c );
uint32_t xifo32_get_used( xifo32_t *c );
uint32_t xifo32_get_full( xifo32_t *c );
uint32_t xifo32_get_free( xifo32_t *c );
#ifdef __cplusplus
}
#endif
#endif

#if xIFO_USE_16BIT == TRUE
/**
 * @brief   Circular Buffer object.
 * @details This struct holds the object of a circular buffer
 */
typedef struct  {
    /* Pointers: */
    uint16_t *startpool;    /**< @brief First element in pool */
    uint16_t *endpool;      /**< @brief Last element in pool */
    uint16_t *read;         /**< @brief Read pointer */
    uint16_t *write;        /**< @brief Write pointer */
    /* Variables: */
    uint32_t full;          /**< @brief Flag indicating buffer is full */
    uint32_t count;         /**< @brief Number of elements used */
    uint32_t size;          /**< @brief Size of buffer */
}xifo16_t;

/**
 * @brief   Circular Buffer memory pool type.
 */
typedef uint16_t xifo16_pool_t;

#ifdef __cplusplus
extern "C" {
#endif
/* xifo Common */
void xifo16_init( xifo16_t *c, uint32_t size, uint16_t *startpool);
void xifo16_clear( xifo16_t *c);
uint32_t xifo16_write( xifo16_t *c, uint16_t data);
/* FIFO use */
uint16_t xifo16_read_lr( xifo16_t *c, uint32_t index);
uint16_t xifo16_pop_lr( xifo16_t *c);
/* LIFO use */
uint16_t xifo16_read_mr( xifo16_t *c, uint32_t index);
uint16_t xifo16_pop_mr( xifo16_t *c);
/* Extractors */
uint32_t xifo16_get_size( xifo16_t *c);
uint32_t xifo16_get_used( xifo16_t *c);
uint32_t xifo16_get_full( xifo16_t *c);
uint32_t xifo16_get_free( xifo16_t *c);
#ifdef __cplusplus
}
#endif
#endif

#if xIFO_USE_8BIT == TRUE
/**
 * @brief   Circular Buffer object.
 * @details This struct holds the object of a circular buffer
 */
typedef struct  {
    /* Pointers: */
    uint8_t *startpool;     /**< @brief First element in pool */
    uint8_t *endpool;       /**< @brief Last element in pool */
    uint8_t *read;          /**< @brief Read pointer */
    uint8_t *write;         /**< @brief Write pointer */
    /* Variables: */
    uint32_t full;          /**< @brief Flag indicating buffer is full */
    uint32_t count;         /**< @brief Number of elements used */
    uint32_t size;          /**< @brief Size of buffer */
}xifo8_t;

/**< @brief   Circular Buffer memory pool type. */
typedef uint8_t xifo8_pool_t;

#ifdef __cplusplus
extern "C" {
#endif
/* xifo Common */
void xifo8_init(xifo8_t *c, uint32_t size, uint8_t *startpool );
void xifo8_clear( xifo8_t *c );
uint32_t xifo8_write( xifo8_t *c, uint8_t data );
/* FIFO use */
uint8_t xifo8_read_lr( xifo8_t *c, uint32_t index );
uint8_t xifo8_pop_lr( xifo8_t *c );
/* LIFO use */
uint8_t xifo8_read_mr( xifo8_t *c, uint32_t index );
uint8_t xifo8_pop_mr( xifo8_t *c );
/* Extractors */
uint32_t xifo8_get_size( xifo8_t *c );
uint32_t xifo8_get_used( xifo8_t *c );
uint32_t xifo8_get_full( xifo8_t *c );
uint32_t xifo8_get_free( xifo8_t *c );
#ifdef __cplusplus
}
#endif
#endif

#endif //_xifo_H_

/** @} */