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

Files at this revision

API Documentation at this revision

Comitter:
jeroen3
Date:
Mon Oct 28 18:39:36 2013 +0000
Child:
1:5f59aa9b86ed
Commit message:
Initial

Changed in this revision

xIFO.c Show annotated file Show diff for this revision Revisions of this file
xIFO.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xIFO.c	Mon Oct 28 18:39:36 2013 +0000
@@ -0,0 +1,287 @@
+
+ /**
+ * @file    xifo.c
+ * @brief   xifo circular buffer
+ * @details xifo supplies object oriented circular buffer with 32 bit size elements. \n
+ *                     To use either as FIFO (First In First Out) or as FILO (First In Last Out)
+ *
+ * @Author    Jeroen Lodder
+ * @Date        April 2013
+ * @version 2
+ *
+ * @{
+ */
+#include "xifo.h"
+
+/**
+ * @brief   Initialise buffer object structure.
+ *
+ * @note    Does not clear memory pool.
+ *
+ * @param[in] c   Pointer to @p xifo_t object used for configuration.
+ * @param[in] s   Number of elements buffer can hold (size).
+ * @param[in] sp  Start of pre-allocated memory pool.
+ */
+void xifo_init(xifo_t *c, uint32_t s, uint32_t *sp){
+    c->startpool        = sp;
+    c->endpool          = &sp[s-1];
+    c->size             = s;
+    c->full             = 0;
+    c->elementcount     = 0;
+    c->read             = sp;
+    c->write            = sp;
+}
+
+/**
+ * @brief   Clear buffer contents
+ *
+ * @note    Must be used on initialised buffer object.
+ *
+ * @param[in] c   Pointer to @p xifo_t object.
+ */
+void xifo_clear(xifo_t *c){
+    c->ptemp = c->startpool;
+    while(c->ptemp <= c->endpool){
+        *c->ptemp++ = 0;        
+    }
+}
+
+/**
+ * @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[elementcount] the most recent element is returned.
+ *                    This makes it possible to peek in fifo.
+ *
+ * @param[in] c           Pointer to @p xifo_t used for configuration.
+ * @param[in] index   Index relative from least recent
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_read_lr(xifo_t *c, uint32_t index){
+    /* Verify there is valid data to read */
+    if(index+1 > c->elementcount){
+        return 0;    /* Nothing to read there */
+    }
+    /* Calculate index of oldest element */
+    index = (c->elementcount-1) - index;
+    /* Set pointer */
+    c->ptemp = (c->read) - index;
+    if(c->ptemp < c->startpool){
+        /* We 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 */
+        c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
+    }
+    /* Read most recent */
+    return *c->ptemp;
+}
+
+/**
+ * @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[elementcount] the oldest element is returned.
+ *                    This makes it possible to keep history. For DSP application.
+ *
+ * @param[in] c           Pointer to @p xifo_t used for configuration.
+ * @param[in] index   Index relative from most recent
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_read_mr(xifo_t *c, uint32_t index){
+    /* Verify there is valid data to read */
+    if(index+1 > c->elementcount){
+        return 0;    /* Nothing to read there */
+    }
+    /* Set pointer */
+    c->ptemp = (c->read) - index;
+    /* Validate pointer */
+    if(c->ptemp < c->startpool){
+        /* We 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 */
+        c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
+    }
+    /* Read most recent */
+    return *c->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_t used for configuration.
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_pop_mr(xifo_t *c){
+    /* Verify there is valid data read */
+    if(c->elementcount == 0){
+        return 0;    /* Nothing to read there */
+    }
+    /* Read */
+    c->temp = *c->read;
+    /* Empty */
+    *c->read = 0;
+    /* Most recent element read, return write pointer */
+    c->write = c->read;
+    /* Decrement read pointer */
+    c->read--;
+    /* Validate pointer */
+    if( c->read < c->startpool ){
+        /* We exceeded pool boundaries */
+        c->read = c->endpool;
+    }
+    /* Reduce elementcount */
+    c->elementcount--;
+    if(c->elementcount < c->size)
+        c->full = 0;
+    return c->temp;
+}
+
+/**
+ * @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_t used for configuration.
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_pop_lr(xifo_t *c){    
+    /* Verify there is valid data read */
+    if(c->elementcount == 0){
+        return 0;    /* Nothing to read there */
+    }
+    /* Derive least recent buffer element */
+    c->ptemp = c->read+1 - c->elementcount;
+    /* Validate pointer */
+    if(c->ptemp < c->startpool){
+        /* We 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 */
+        c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
+    }
+    /* Read oldest buffer element */
+    { /* block with temporary variable to prevent stack use */
+        register uint32_t element;
+        /* Read to temp register */
+        element = *c->ptemp;
+        /* Empty */
+        *c->ptemp = 0;
+        /* Clear temp register */
+        c->temp = element;
+    }
+    /* Reduce elementcount */
+    c->elementcount--;
+    /* Check full flag */
+    if(c->elementcount < c->size)
+        c->full = 0;
+    return c->temp;
+}
+
+/**
+ * @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_t used for configuration.
+ * @param[in] data    Data to add to buffer
+ *
+ * @return    Number of free buffer elements
+ */
+uint32_t xifo_write(xifo_t *c, uint32_t data){    
+    /* Write data */
+    *c->write = data;
+    /* Update read pointer to most recent element */
+    c->read = c->write;
+    /* Write pointer increment */
+    c->write += 1;
+    /* Validate pointer */
+    if( c->write > c->endpool){
+          /* We exceeded pool boundaries */
+            c->write = c->startpool;
+    }
+    /* Update elementcount */
+    c->elementcount++;
+    /* Verify full */
+    if( c->elementcount >= c->size ){
+        c->full = 1;
+        c->elementcount = c->size;
+    }
+    /* return free elements count */
+    return c->size - c->elementcount;
+}
+
+/**
+ * @brief   Get buffer size
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    Size of memory pool in elements
+ */
+uint32_t xifo_get_size(xifo_t *c){
+    return c->size;
+}
+
+/**
+ * @brief   Get number of used elements
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    Number of used buffer elements
+ */
+uint32_t xifo_get_used(xifo_t *c){
+    return c->elementcount;
+}
+
+/**
+* @brief   Get number of free elements
+*
+* @param[in] c    Pointer to @p xifo_t used for configuration.
+*
+* @return    Number of free elements
+*/
+uint32_t xifo_get_free(xifo_t *c){
+    return c->size - c->elementcount;
+}
+
+/**
+ * @brief   Get full flag
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    1 if full
+ */
+uint32_t xifo_get_full(xifo_t *c){
+    return c->full;
+}
+
+/** @} */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xIFO.h	Mon Oct 28 18:39:36 2013 +0000
@@ -0,0 +1,92 @@
+ 
+ /**
+ * @file    xifo.h
+ * @brief   xifo circular buffer
+ * @details xifo supplies object oriented circular buffer with 32 bit size elements. \n
+ *                     To use either as FIFO (First In First Out) or as FILO (First In Last Out)
+ *
+ * @author    Jeroen Lodder
+ * @date        April 2013
+ * @version 2
+ *
+ * @{
+ */
+ 
+ /**
+ *    Code has been tested on Cortex M0 (LPC1114)
+ *  Performance table, number of core clocks
+ *    Measured with a timer before and after
+ *    r1 = timer->TC
+ *        test_function 
+ *  r2 = timer->TC
+ *
+ *  Function    Speed        Worst Case
+ *
+ *  write            69            71
+ *  read_mr        59      59
+ *  read_lr        63      70
+ *  pop_mr        76      78
+ *    pop_lr        45      45
+ *
+ */
+
+#ifndef _xifo_H_
+#define _xifo_H_
+
+#include <inttypes.h>
+
+#if defined(__arm__)  || defined(__DOXYGEN__)
+#pragma anon_unions                /**< Allow unnamed unions */
+#endif
+
+/**
+ * @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 elementcount;/**< @brief Number of elements used */
+        uint32_t size;                /**< @brief Size of buffer */
+/* Locally used in functions to prevent stack use: */
+        /**< @brief union to prevent lvalue typecasting */  
+        union {                         
+            uint32_t temp;            /**< @brief temp variable and padding for even sized block */
+            uint32_t *ptemp;         /**< @brief temp variable and padding for even sized block */
+        };
+}xifo_t;
+
+/**
+ * @brief   Circular Buffer memory pool type.
+ */
+typedef unsigned int xifo_pool_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* xifo Common */
+void xifo_init(xifo_t *c, uint32_t size, uint32_t *startpool);
+void xifo_clear(xifo_t *c);
+uint32_t xifo_write(xifo_t *c, uint32_t data);
+/* FIFO use */
+uint32_t xifo_read_lr(xifo_t *c, uint32_t index);
+uint32_t xifo_pop_lr(xifo_t *c);
+/* LIFO use */
+uint32_t xifo_read_mr(xifo_t *c, uint32_t index);
+uint32_t xifo_pop_mr(xifo_t *c);
+/* Extractors */
+uint32_t xifo_get_size(xifo_t *c);
+uint32_t xifo_get_used(xifo_t *c);
+uint32_t xifo_get_full(xifo_t *c);
+uint32_t xifo_get_free(xifo_t *c);
+#ifdef __cplusplus
+}
+#endif
+#endif //_xifo_H_
+
+/** @} */