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_ /** @} */