Jeroen Lodder / xIFO
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers xIFO.h Source File

xIFO.h

00001 /**
00002  * @file    xifo.h
00003  * @brief   xifo circular buffer for all elements
00004  * @details xifo supplies object oriented circular buffer with x bit size elements. \n
00005  *          To use either as FIFO (First In First Out) or as FILO (First In Last Out)
00006  *          Below are defines to disable or enable any xIFO type you like.
00007  *
00008  * @author  Jeroen Lodder
00009  * @date    March 2014
00010  * @version 3
00011  * 
00012  * Copyright (c) 2014 Jeroen Lodder
00013  * 
00014  * Permission is hereby granted, free of charge, to any person obtaining a copy
00015  * of this software and associated documentation files (the "Software"), to deal
00016  * in the Software without restriction, including without limitation the rights
00017  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00018  * copies of the Software, and to permit persons to whom the Software is
00019  * furnished to do so, subject to the following conditions:
00020  * 
00021  * The above copyright notice and this permission notice shall be included in all
00022  * copies or substantial portions of the Software.
00023  * 
00024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00025  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00026  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00027  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00028  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00029  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00030  * SOFTWARE.
00031  *
00032  * @{
00033  */
00034 #ifndef _xifo_H_
00035 #define _xifo_H_
00036  
00037 #include <inttypes.h>
00038 
00039 #if !defined(TRUE) || defined(__DOXYGEN__)
00040 #define TRUE    (1)
00041 #endif
00042 #if !defined(FALSE) || defined(__DOXYGEN__)
00043 #define FALSE   !(TRUE)
00044 #endif
00045  
00046 #ifdef __cplusplus
00047 #if !defined(xIFO_USE_CPP) || defined(__DOXYGEN__)
00048 #define xIFO_USE_CPP            TRUE
00049 #endif
00050 #endif
00051 
00052 #if !defined(xIFO_USE_64BIT) || defined(__DOXYGEN__)
00053 #define xIFO_USE_64BIT          TRUE
00054 #endif
00055 
00056 #if !defined(xIFO_USE_32BIT) || defined(__DOXYGEN__)
00057 #define xIFO_USE_32BIT          TRUE
00058 #endif
00059 
00060 #if !defined(xIFO_USE_16BIT) || defined(__DOXYGEN__)
00061 #define xIFO_USE_16BIT          TRUE
00062 #endif
00063 
00064 #if !defined(xIFO_USE_8BIT) || defined(__DOXYGEN__)
00065 #define xIFO_USE_8BIT           TRUE
00066 #endif
00067 
00068 
00069 #if xIFO_USE_CPP == TRUE
00070 /**
00071  * @brief   Circular Buffer object.
00072  * @details This class holds the object of a circular buffer
00073  */
00074 template <class xifo_dtype>
00075 class Xifo
00076 {
00077 public:
00078     /**
00079      * @brief   Initialise xifo.
00080      * @note    Does not clear memory pool.
00081      * @param[in] Number of elements buffer can hold (size).
00082      */
00083     Xifo(uint32_t size)
00084     {
00085         startpool = new xifo_dtype[size];
00086         endpool         = &startpool[size-1];
00087         isize           = size;
00088         ifull           = 0;
00089         icount           = 0;
00090         read            = startpool;
00091         pwrite          = startpool;
00092     }
00093 
00094     /**
00095      * @brief   Initialise xifo.
00096      * @note    Does not clear memory pool.
00097      * @param[in] Number of elements buffer can hold (size).
00098      * @param[in] Start of pre-allocated memory pool.
00099      */
00100     Xifo(uint32_t size, xifo_dtype *sp)
00101     {
00102         startpool       = sp;
00103         endpool         = &sp[size-1];
00104         isize           = size;
00105         ifull           = 0;
00106         icount            = 0;
00107         read            = sp;
00108         pwrite          = sp;
00109     }
00110 
00111     /**
00112      * @brief   Deinitialise (and deallocate) buffer xifo.
00113      * @note    Does not clear memory pool.
00114      */
00115     ~Xifo(void)
00116     {
00117         if(dynamic){
00118             delete startpool;
00119         }
00120     }
00121 
00122     /**
00123      * @brief   Clear buffer memory pool
00124      * @note    Must be used on initialised buffer object.
00125      * @param[in] c   Pointer to @p xifo_SIZETYPE_t object.
00126      */
00127     void clear(void)
00128     {
00129         register xifo_dtype *ptemp = startpool;
00130         while(ptemp <= endpool){
00131             *ptemp++ = 0;
00132         }
00133     }
00134     
00135      /**
00136      * @brief   Reset buffer
00137      * @note    Must be used on initialised buffer object.
00138      * @param[in] c   Pointer to @p xifo_SIZETYPE_t object.
00139      */
00140     void reset(void)
00141     {
00142         register xifo_dtype *ptemp = startpool;
00143         while(ptemp <= endpool){
00144             *ptemp++ = 0;
00145         }
00146         ifull       = 0;
00147         icount      = 0;
00148         read        = startpool;
00149         pwrite      = startpool;
00150     }
00151 
00152     /**
00153      * @brief   Write to buffer
00154      *
00155      * @note    Readpointer is automatically set to the last added element.
00156      *
00157      * @warning Consider this opertaion as atomic!
00158      *
00159      * @details Adds a value to the buffer.
00160      *                  Automatically overwrites oldest elements when full.
00161      *
00162      * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
00163      * @param[in] data  Data to add to buffer
00164      *
00165      * @return  Number of free buffer elements
00166      */
00167     uint32_t write(xifo_dtype data)
00168     {
00169         /* Write data */
00170         *pwrite = data;
00171         /* Update read pointer to most recent element */
00172         read = pwrite;
00173         /* Write pointer increment */
00174         pwrite += 1;
00175         /* Validate pointer */
00176         if( pwrite > endpool){
00177             /* Exceeded pool boundaries */
00178             pwrite = startpool;
00179         }
00180         /* Update count */
00181         icount++;
00182         /* Verify full */
00183         if( icount >= isize ){
00184             ifull = 1;
00185             icount = isize;
00186         }
00187         /* return free elements count */
00188         return isize - icount;
00189     }
00190 
00191     /**
00192      * @brief   Read from buffer (lr) Least Recent oriented (fifo)
00193      *
00194      * @note    Buffer state will be preserved
00195      *
00196      * @warning Consider this opertaion as atomic!
00197      *
00198      * @details Read n elements from the oldest element to the most recent.
00199      *                  As for index[0] the least recently added element is returned.
00200      *                  And for index[count] the most recent element is returned.
00201      *                  This makes it possible to peek in fifo.
00202      *
00203      * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
00204      * @param[in] index   Index relative from least recent
00205      *
00206      * @return  Contents of element or 0 if failed (element can hold 0)
00207      */
00208     xifo_dtype read_lr(uint32_t index)
00209     {
00210         register xifo_dtype *ptemp;
00211         /* Verify there is valid data to read */
00212         if(index+1 > icount){
00213             return 0;
00214         }
00215         /* Calculate index of oldest element */
00216         index = (icount-1) - index;
00217         /* Set pointer */
00218         ptemp = (read) - index;
00219         if(ptemp < startpool){
00220             /* Exceeded pool boundaries */
00221             /* Calculate overshoot (startpool - indexptr) and subtract from end */
00222             /* Since one element of overshoot results in end - 1 you would miss the last value */
00223             ptemp = (endpool+1) - (startpool - ptemp);
00224         }
00225         /* Read most recent */
00226         return *ptemp;
00227     }
00228 
00229     /**
00230      * @brief   Pop (lr) least recent from buffer (fifo)
00231      *
00232      * @note    Buffer state will be altered
00233      *
00234      * @warning Consider this opertaion as atomic!
00235      *
00236      * @details Read and remove the least recently added from the buffer.
00237      *                  Using this results in a fifo type of buffer.
00238      *
00239      * @param[in] c Pointer to @p xifo_SIZETYPE_t used for configuration.
00240      *
00241      * @return  Contents of element or 0 if failed (element can hold 0)
00242      */
00243     xifo_dtype pop_lr()
00244     {
00245         register xifo_dtype *ptemp;
00246         xifo_dtype temp;
00247         /* Verify there is valid data read */
00248         if(icount == 0){
00249             return 0;
00250         }
00251         /* Derive least recent buffer element */
00252         ptemp = read+1 - icount;
00253         /* Validate pointer */
00254         if(ptemp < startpool){
00255             /* Exceeded pool boundaries */
00256             /* Calculate overshoot (startpool - indexptr) and subtract from end */
00257             /* Since one element of overshoot results in end - 1 you would miss the last value */
00258             ptemp = (endpool+1) - (startpool - ptemp);
00259         }
00260         /* Read oldest buffer element */
00261         /* Read to temp register */
00262         temp = *ptemp;
00263         /* Empty buffer element */
00264         *ptemp = 0;
00265         /* Reduce count */
00266         icount--;
00267         /* Check full flag */
00268         if(icount < isize)
00269             ifull = 0;
00270         return temp;
00271     }
00272 
00273     /**
00274      * @brief   Read from buffer (mr) Most Recent oriented (filo)
00275      *
00276      * @note    Buffer state will be preserved
00277      *
00278      * @warning Consider this opertaion as atomic!
00279      *
00280      * @details Read n elements back in time.
00281      *                  As for index[0] the most recently added element is returned.
00282      *                  And for index[count] the oldest element is returned.
00283      *                  This makes it possible to keep history. For DSP application.
00284      *
00285      * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
00286      * @param[in] index   Index relative from most recent
00287      *
00288      * @return  Contents of element or 0 if failed (element can hold 0)
00289      */
00290     xifo_dtype read_mr(uint32_t index)
00291     {
00292         register xifo_dtype *ptemp;
00293         /* Verify there is valid data to read */
00294         if(index+1 > icount){
00295             return 0;
00296         }
00297         /* Set pointer */
00298         ptemp = read - index;
00299         /* Validate pointer */
00300         if(ptemp < startpool){
00301             /* Exceeded pool boundaries */
00302             /* Calculate overshoot (startpool - indexptr) and subtract from end */
00303             /* Since one element of overshoot results in end - 1 you would miss the last value */
00304             ptemp = (endpool+1) - (startpool - ptemp);
00305         }
00306         /* Read most recent */
00307         return *ptemp;
00308     }
00309 
00310     /**
00311      * @brief   Pop (mr) most recent from buffer (filo)
00312      *
00313      * @note    Buffer state will be altered
00314      *
00315      * @warning Consider this opertaion as atomic!
00316      *
00317      * @details Read and remove the most recently added from the buffer.
00318      *                  Using this results in a stack type of buffer.
00319      *
00320      * @param[in] c         Pointer to @p xifo_SIZETYPE_t used for configuration.
00321      *
00322      * @return  Contents of element or 0 if failed (element can hold 0)
00323      */
00324     xifo_dtype pop_mr()
00325     {
00326         register xifo_dtype temp;
00327         /* Verify there is valid data read */
00328         if(icount == 0){
00329             return 0;
00330         }
00331         /* Read */
00332         temp = *read;
00333         /* Empty */
00334         *read = 0;
00335         /* Most recent element read, return write pointer */
00336         pwrite = read;
00337         /* Decrement read pointer */
00338         read--;
00339         /* Validate pointer */
00340         if( read < startpool ){
00341             /* Exceeded pool boundaries */
00342             read = endpool;
00343         }
00344         /* Reduce count */
00345         icount--;
00346         if(icount < isize)
00347             ifull = 0;
00348         return temp;
00349     }
00350 
00351     /* Extractors */
00352     uint32_t size(){ return isize; }         /**< @brief   Get buffer size */
00353     uint32_t used(){ return icount; }        /**< @brief   Get number of used elements */
00354     uint32_t full(){ return ifull; }         /**< @brief   Get full flag */
00355     uint32_t free(){ return isize-icount; }   /**< @brief   Get number of free elements */
00356 private:
00357     bool dynamic;
00358     xifo_dtype *startpool;         /**< @brief First element in pool */
00359     xifo_dtype *endpool;    /**< @brief Last element in pool */
00360     xifo_dtype *read;       /**< @brief Read pointer */
00361     xifo_dtype *pwrite;     /**< @brief Write pointer */
00362     /* Variables: */
00363     uint32_t ifull;          /**< @brief Flag indicating buffer is full */
00364     uint32_t icount;         /**< @brief Number of elements used */
00365     uint32_t isize;          /**< @brief Size of buffer */
00366 };
00367 #endif
00368 
00369 #if xIFO_USE_64BIT == TRUE
00370 /**
00371  * @brief   Circular Buffer object.
00372  * @details This struct holds the object of a circular buffer
00373  */
00374 typedef struct  {
00375     /* Pointers: */
00376     uint64_t *startpool;    /**< @brief First element in pool */
00377     uint64_t *endpool;      /**< @brief Last element in pool */
00378     uint64_t *read;         /**< @brief Read pointer */
00379     uint64_t *write;        /**< @brief Write pointer */
00380     /* Variables: */
00381     uint32_t full;          /**< @brief Flag indicating buffer is full */
00382     uint32_t count;         /**< @brief Number of elements used */
00383     uint32_t size;          /**< @brief Size of buffer */
00384 }xifo64_t;
00385 
00386 /**< @brief   Circular Buffer memory pool type. */
00387 typedef uint64_t xifo64_pool_t;
00388 
00389 #ifdef __cplusplus
00390 extern "C" {
00391 #endif
00392 /* xifo Common */
00393 void xifo64_init( xifo64_t *c, uint32_t size, uint64_t *startpool );
00394 void xifo64_clear( xifo64_t *c );
00395 uint32_t xifo64_write( xifo64_t *c, uint64_t data );
00396 /* FIFO use */
00397 uint64_t xifo64_read_lr( xifo64_t *c, uint32_t index );
00398 uint64_t xifo64_pop_lr( xifo64_t *c );
00399 /* LIFO use */
00400 uint64_t xifo64_read_mr( xifo64_t *c, uint32_t index );
00401 uint64_t xifo64_pop_mr( xifo64_t *c );
00402 /* Extractors */
00403 uint32_t xifo64_get_size( xifo64_t *c );
00404 uint32_t xifo64_get_used( xifo64_t *c );
00405 uint32_t xifo64_get_full( xifo64_t *c );
00406 uint32_t xifo64_get_free( xifo64_t *c );
00407 #ifdef __cplusplus
00408 }
00409 #endif
00410 #endif
00411 
00412 #if xIFO_USE_32BIT == TRUE
00413 /**
00414  * @brief   Circular Buffer object.
00415  * @details This struct holds the object of a circular buffer
00416  */
00417 typedef struct  {
00418     /* Pointers: */
00419     uint32_t *startpool;    /**< @brief First element in pool */
00420     uint32_t *endpool;      /**< @brief Last element in pool */
00421     uint32_t *read;         /**< @brief Read pointer */
00422     uint32_t *write;        /**< @brief Write pointer */
00423     /* Variables: */
00424     uint32_t full;          /**< @brief Flag indicating buffer is full */
00425     uint32_t count;         /**< @brief Number of elements used */
00426     uint32_t size;          /**< @brief Size of buffer */
00427 }xifo32_t;
00428 
00429 /**< @brief   Circular Buffer memory pool type. */
00430 typedef uint32_t xifo32_pool_t;
00431 
00432 #ifdef __cplusplus
00433 extern "C" {
00434 #endif
00435 /* xifo Common */
00436 void xifo32_init( xifo32_t *c, uint32_t size, uint32_t *startpool );
00437 void xifo32_clear( xifo32_t *c );
00438 uint32_t xifo32_write( xifo32_t *c, uint32_t data );
00439 /* FIFO use */
00440 uint32_t xifo32_read_lr( xifo32_t *c, uint32_t index );
00441 uint32_t xifo32_pop_lr( xifo32_t *c );
00442 /* LIFO use */
00443 uint32_t xifo32_read_mr( xifo32_t *c, uint32_t index );
00444 uint32_t xifo32_pop_mr( xifo32_t *c );
00445 /* Extractors */
00446 uint32_t xifo32_get_size( xifo32_t *c );
00447 uint32_t xifo32_get_used( xifo32_t *c );
00448 uint32_t xifo32_get_full( xifo32_t *c );
00449 uint32_t xifo32_get_free( xifo32_t *c );
00450 #ifdef __cplusplus
00451 }
00452 #endif
00453 #endif
00454 
00455 #if xIFO_USE_16BIT == TRUE
00456 /**
00457  * @brief   Circular Buffer object.
00458  * @details This struct holds the object of a circular buffer
00459  */
00460 typedef struct  {
00461     /* Pointers: */
00462     uint16_t *startpool;    /**< @brief First element in pool */
00463     uint16_t *endpool;      /**< @brief Last element in pool */
00464     uint16_t *read;         /**< @brief Read pointer */
00465     uint16_t *write;        /**< @brief Write pointer */
00466     /* Variables: */
00467     uint32_t full;          /**< @brief Flag indicating buffer is full */
00468     uint32_t count;         /**< @brief Number of elements used */
00469     uint32_t size;          /**< @brief Size of buffer */
00470 }xifo16_t;
00471 
00472 /**
00473  * @brief   Circular Buffer memory pool type.
00474  */
00475 typedef uint16_t xifo16_pool_t;
00476 
00477 #ifdef __cplusplus
00478 extern "C" {
00479 #endif
00480 /* xifo Common */
00481 void xifo16_init( xifo16_t *c, uint32_t size, uint16_t *startpool);
00482 void xifo16_clear( xifo16_t *c);
00483 uint32_t xifo16_write( xifo16_t *c, uint16_t data);
00484 /* FIFO use */
00485 uint16_t xifo16_read_lr( xifo16_t *c, uint32_t index);
00486 uint16_t xifo16_pop_lr( xifo16_t *c);
00487 /* LIFO use */
00488 uint16_t xifo16_read_mr( xifo16_t *c, uint32_t index);
00489 uint16_t xifo16_pop_mr( xifo16_t *c);
00490 /* Extractors */
00491 uint32_t xifo16_get_size( xifo16_t *c);
00492 uint32_t xifo16_get_used( xifo16_t *c);
00493 uint32_t xifo16_get_full( xifo16_t *c);
00494 uint32_t xifo16_get_free( xifo16_t *c);
00495 #ifdef __cplusplus
00496 }
00497 #endif
00498 #endif
00499 
00500 #if xIFO_USE_8BIT == TRUE
00501 /**
00502  * @brief   Circular Buffer object.
00503  * @details This struct holds the object of a circular buffer
00504  */
00505 typedef struct  {
00506     /* Pointers: */
00507     uint8_t *startpool;     /**< @brief First element in pool */
00508     uint8_t *endpool;       /**< @brief Last element in pool */
00509     uint8_t *read;          /**< @brief Read pointer */
00510     uint8_t *write;         /**< @brief Write pointer */
00511     /* Variables: */
00512     uint32_t full;          /**< @brief Flag indicating buffer is full */
00513     uint32_t count;         /**< @brief Number of elements used */
00514     uint32_t size;          /**< @brief Size of buffer */
00515 }xifo8_t;
00516 
00517 /**< @brief   Circular Buffer memory pool type. */
00518 typedef uint8_t xifo8_pool_t;
00519 
00520 #ifdef __cplusplus
00521 extern "C" {
00522 #endif
00523 /* xifo Common */
00524 void xifo8_init(xifo8_t *c, uint32_t size, uint8_t *startpool );
00525 void xifo8_clear( xifo8_t *c );
00526 uint32_t xifo8_write( xifo8_t *c, uint8_t data );
00527 /* FIFO use */
00528 uint8_t xifo8_read_lr( xifo8_t *c, uint32_t index );
00529 uint8_t xifo8_pop_lr( xifo8_t *c );
00530 /* LIFO use */
00531 uint8_t xifo8_read_mr( xifo8_t *c, uint32_t index );
00532 uint8_t xifo8_pop_mr( xifo8_t *c );
00533 /* Extractors */
00534 uint32_t xifo8_get_size( xifo8_t *c );
00535 uint32_t xifo8_get_used( xifo8_t *c );
00536 uint32_t xifo8_get_full( xifo8_t *c );
00537 uint32_t xifo8_get_free( xifo8_t *c );
00538 #ifdef __cplusplus
00539 }
00540 #endif
00541 #endif
00542 
00543 #endif //_xifo_H_
00544 
00545 /** @} */