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

Committer:
jeroen3
Date:
Mon Oct 28 19:20:00 2013 +0000
Revision:
1:5f59aa9b86ed
Parent:
0:a04dc0c57d20
Fix case sensitive include

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jeroen3 0:a04dc0c57d20 1
jeroen3 0:a04dc0c57d20 2 /**
jeroen3 0:a04dc0c57d20 3 * @file xifo.c
jeroen3 0:a04dc0c57d20 4 * @brief xifo circular buffer
jeroen3 0:a04dc0c57d20 5 * @details xifo supplies object oriented circular buffer with 32 bit size elements. \n
jeroen3 0:a04dc0c57d20 6 * To use either as FIFO (First In First Out) or as FILO (First In Last Out)
jeroen3 0:a04dc0c57d20 7 *
jeroen3 0:a04dc0c57d20 8 * @Author Jeroen Lodder
jeroen3 0:a04dc0c57d20 9 * @Date April 2013
jeroen3 0:a04dc0c57d20 10 * @version 2
jeroen3 0:a04dc0c57d20 11 *
jeroen3 0:a04dc0c57d20 12 * @{
jeroen3 0:a04dc0c57d20 13 */
jeroen3 1:5f59aa9b86ed 14 #include "xIFO.h"
jeroen3 0:a04dc0c57d20 15
jeroen3 0:a04dc0c57d20 16 /**
jeroen3 0:a04dc0c57d20 17 * @brief Initialise buffer object structure.
jeroen3 0:a04dc0c57d20 18 *
jeroen3 0:a04dc0c57d20 19 * @note Does not clear memory pool.
jeroen3 0:a04dc0c57d20 20 *
jeroen3 0:a04dc0c57d20 21 * @param[in] c Pointer to @p xifo_t object used for configuration.
jeroen3 0:a04dc0c57d20 22 * @param[in] s Number of elements buffer can hold (size).
jeroen3 0:a04dc0c57d20 23 * @param[in] sp Start of pre-allocated memory pool.
jeroen3 0:a04dc0c57d20 24 */
jeroen3 0:a04dc0c57d20 25 void xifo_init(xifo_t *c, uint32_t s, uint32_t *sp){
jeroen3 0:a04dc0c57d20 26 c->startpool = sp;
jeroen3 0:a04dc0c57d20 27 c->endpool = &sp[s-1];
jeroen3 0:a04dc0c57d20 28 c->size = s;
jeroen3 0:a04dc0c57d20 29 c->full = 0;
jeroen3 0:a04dc0c57d20 30 c->elementcount = 0;
jeroen3 0:a04dc0c57d20 31 c->read = sp;
jeroen3 0:a04dc0c57d20 32 c->write = sp;
jeroen3 0:a04dc0c57d20 33 }
jeroen3 0:a04dc0c57d20 34
jeroen3 0:a04dc0c57d20 35 /**
jeroen3 0:a04dc0c57d20 36 * @brief Clear buffer contents
jeroen3 0:a04dc0c57d20 37 *
jeroen3 0:a04dc0c57d20 38 * @note Must be used on initialised buffer object.
jeroen3 0:a04dc0c57d20 39 *
jeroen3 0:a04dc0c57d20 40 * @param[in] c Pointer to @p xifo_t object.
jeroen3 0:a04dc0c57d20 41 */
jeroen3 0:a04dc0c57d20 42 void xifo_clear(xifo_t *c){
jeroen3 0:a04dc0c57d20 43 c->ptemp = c->startpool;
jeroen3 0:a04dc0c57d20 44 while(c->ptemp <= c->endpool){
jeroen3 0:a04dc0c57d20 45 *c->ptemp++ = 0;
jeroen3 0:a04dc0c57d20 46 }
jeroen3 0:a04dc0c57d20 47 }
jeroen3 0:a04dc0c57d20 48
jeroen3 0:a04dc0c57d20 49 /**
jeroen3 0:a04dc0c57d20 50 * @brief Read from buffer (lr) Least Recent oriented (fifo)
jeroen3 0:a04dc0c57d20 51 *
jeroen3 0:a04dc0c57d20 52 * @note Buffer state will be preserved
jeroen3 0:a04dc0c57d20 53 *
jeroen3 0:a04dc0c57d20 54 * @warning Consider this opertaion as atomic!
jeroen3 0:a04dc0c57d20 55 *
jeroen3 0:a04dc0c57d20 56 * @details Read n elements from the oldest element to the most recent.
jeroen3 0:a04dc0c57d20 57 * As for index[0] the least recently added element is returned.
jeroen3 0:a04dc0c57d20 58 * And for index[elementcount] the most recent element is returned.
jeroen3 0:a04dc0c57d20 59 * This makes it possible to peek in fifo.
jeroen3 0:a04dc0c57d20 60 *
jeroen3 0:a04dc0c57d20 61 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 62 * @param[in] index Index relative from least recent
jeroen3 0:a04dc0c57d20 63 *
jeroen3 0:a04dc0c57d20 64 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 0:a04dc0c57d20 65 */
jeroen3 0:a04dc0c57d20 66 uint32_t xifo_read_lr(xifo_t *c, uint32_t index){
jeroen3 0:a04dc0c57d20 67 /* Verify there is valid data to read */
jeroen3 0:a04dc0c57d20 68 if(index+1 > c->elementcount){
jeroen3 0:a04dc0c57d20 69 return 0; /* Nothing to read there */
jeroen3 0:a04dc0c57d20 70 }
jeroen3 0:a04dc0c57d20 71 /* Calculate index of oldest element */
jeroen3 0:a04dc0c57d20 72 index = (c->elementcount-1) - index;
jeroen3 0:a04dc0c57d20 73 /* Set pointer */
jeroen3 0:a04dc0c57d20 74 c->ptemp = (c->read) - index;
jeroen3 0:a04dc0c57d20 75 if(c->ptemp < c->startpool){
jeroen3 0:a04dc0c57d20 76 /* We exceeded pool boundaries */
jeroen3 0:a04dc0c57d20 77 /* Calculate overshoot (startpool - indexptr) and subtract from end */
jeroen3 0:a04dc0c57d20 78 /* Since one element of overshoot results in end - 1 you would miss the last value */
jeroen3 0:a04dc0c57d20 79 c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
jeroen3 0:a04dc0c57d20 80 }
jeroen3 0:a04dc0c57d20 81 /* Read most recent */
jeroen3 0:a04dc0c57d20 82 return *c->ptemp;
jeroen3 0:a04dc0c57d20 83 }
jeroen3 0:a04dc0c57d20 84
jeroen3 0:a04dc0c57d20 85 /**
jeroen3 0:a04dc0c57d20 86 * @brief Read from buffer (mr) Most Recent oriented (filo)
jeroen3 0:a04dc0c57d20 87 *
jeroen3 0:a04dc0c57d20 88 * @note Buffer state will be preserved
jeroen3 0:a04dc0c57d20 89 *
jeroen3 0:a04dc0c57d20 90 * @warning Consider this opertaion as atomic!
jeroen3 0:a04dc0c57d20 91 *
jeroen3 0:a04dc0c57d20 92 * @details Read n elements back in time.
jeroen3 0:a04dc0c57d20 93 * As for index[0] the most recently added element is returned.
jeroen3 0:a04dc0c57d20 94 * And for index[elementcount] the oldest element is returned.
jeroen3 0:a04dc0c57d20 95 * This makes it possible to keep history. For DSP application.
jeroen3 0:a04dc0c57d20 96 *
jeroen3 0:a04dc0c57d20 97 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 98 * @param[in] index Index relative from most recent
jeroen3 0:a04dc0c57d20 99 *
jeroen3 0:a04dc0c57d20 100 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 0:a04dc0c57d20 101 */
jeroen3 0:a04dc0c57d20 102 uint32_t xifo_read_mr(xifo_t *c, uint32_t index){
jeroen3 0:a04dc0c57d20 103 /* Verify there is valid data to read */
jeroen3 0:a04dc0c57d20 104 if(index+1 > c->elementcount){
jeroen3 0:a04dc0c57d20 105 return 0; /* Nothing to read there */
jeroen3 0:a04dc0c57d20 106 }
jeroen3 0:a04dc0c57d20 107 /* Set pointer */
jeroen3 0:a04dc0c57d20 108 c->ptemp = (c->read) - index;
jeroen3 0:a04dc0c57d20 109 /* Validate pointer */
jeroen3 0:a04dc0c57d20 110 if(c->ptemp < c->startpool){
jeroen3 0:a04dc0c57d20 111 /* We exceeded pool boundaries */
jeroen3 0:a04dc0c57d20 112 /* Calculate overshoot (startpool - indexptr) and subtract from end */
jeroen3 0:a04dc0c57d20 113 /* Since one element of overshoot results in end - 1 you would miss the last value */
jeroen3 0:a04dc0c57d20 114 c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
jeroen3 0:a04dc0c57d20 115 }
jeroen3 0:a04dc0c57d20 116 /* Read most recent */
jeroen3 0:a04dc0c57d20 117 return *c->ptemp;
jeroen3 0:a04dc0c57d20 118 }
jeroen3 0:a04dc0c57d20 119
jeroen3 0:a04dc0c57d20 120 /**
jeroen3 0:a04dc0c57d20 121 * @brief Pop (mr) most recent from buffer (filo)
jeroen3 0:a04dc0c57d20 122 *
jeroen3 0:a04dc0c57d20 123 * @note Buffer state will be altered
jeroen3 0:a04dc0c57d20 124 *
jeroen3 0:a04dc0c57d20 125 * @warning Consider this opertaion as atomic!
jeroen3 0:a04dc0c57d20 126 *
jeroen3 0:a04dc0c57d20 127 * @details Read and remove the most recently added from the buffer.
jeroen3 0:a04dc0c57d20 128 * Using this results in a stack type of buffer.
jeroen3 0:a04dc0c57d20 129 *
jeroen3 0:a04dc0c57d20 130 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 131 *
jeroen3 0:a04dc0c57d20 132 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 0:a04dc0c57d20 133 */
jeroen3 0:a04dc0c57d20 134 uint32_t xifo_pop_mr(xifo_t *c){
jeroen3 0:a04dc0c57d20 135 /* Verify there is valid data read */
jeroen3 0:a04dc0c57d20 136 if(c->elementcount == 0){
jeroen3 0:a04dc0c57d20 137 return 0; /* Nothing to read there */
jeroen3 0:a04dc0c57d20 138 }
jeroen3 0:a04dc0c57d20 139 /* Read */
jeroen3 0:a04dc0c57d20 140 c->temp = *c->read;
jeroen3 0:a04dc0c57d20 141 /* Empty */
jeroen3 0:a04dc0c57d20 142 *c->read = 0;
jeroen3 0:a04dc0c57d20 143 /* Most recent element read, return write pointer */
jeroen3 0:a04dc0c57d20 144 c->write = c->read;
jeroen3 0:a04dc0c57d20 145 /* Decrement read pointer */
jeroen3 0:a04dc0c57d20 146 c->read--;
jeroen3 0:a04dc0c57d20 147 /* Validate pointer */
jeroen3 0:a04dc0c57d20 148 if( c->read < c->startpool ){
jeroen3 0:a04dc0c57d20 149 /* We exceeded pool boundaries */
jeroen3 0:a04dc0c57d20 150 c->read = c->endpool;
jeroen3 0:a04dc0c57d20 151 }
jeroen3 0:a04dc0c57d20 152 /* Reduce elementcount */
jeroen3 0:a04dc0c57d20 153 c->elementcount--;
jeroen3 0:a04dc0c57d20 154 if(c->elementcount < c->size)
jeroen3 0:a04dc0c57d20 155 c->full = 0;
jeroen3 0:a04dc0c57d20 156 return c->temp;
jeroen3 0:a04dc0c57d20 157 }
jeroen3 0:a04dc0c57d20 158
jeroen3 0:a04dc0c57d20 159 /**
jeroen3 0:a04dc0c57d20 160 * @brief Pop (lr) least recent from buffer (fifo)
jeroen3 0:a04dc0c57d20 161 *
jeroen3 0:a04dc0c57d20 162 * @note Buffer state will be altered
jeroen3 0:a04dc0c57d20 163 *
jeroen3 0:a04dc0c57d20 164 * @warning Consider this opertaion as atomic!
jeroen3 0:a04dc0c57d20 165 *
jeroen3 0:a04dc0c57d20 166 * @details Read and remove the least recently added from the buffer.
jeroen3 0:a04dc0c57d20 167 * Using this results in a fifo type of buffer.
jeroen3 0:a04dc0c57d20 168 *
jeroen3 0:a04dc0c57d20 169 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 170 *
jeroen3 0:a04dc0c57d20 171 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 0:a04dc0c57d20 172 */
jeroen3 0:a04dc0c57d20 173 uint32_t xifo_pop_lr(xifo_t *c){
jeroen3 0:a04dc0c57d20 174 /* Verify there is valid data read */
jeroen3 0:a04dc0c57d20 175 if(c->elementcount == 0){
jeroen3 0:a04dc0c57d20 176 return 0; /* Nothing to read there */
jeroen3 0:a04dc0c57d20 177 }
jeroen3 0:a04dc0c57d20 178 /* Derive least recent buffer element */
jeroen3 0:a04dc0c57d20 179 c->ptemp = c->read+1 - c->elementcount;
jeroen3 0:a04dc0c57d20 180 /* Validate pointer */
jeroen3 0:a04dc0c57d20 181 if(c->ptemp < c->startpool){
jeroen3 0:a04dc0c57d20 182 /* We exceeded pool boundaries */
jeroen3 0:a04dc0c57d20 183 /* Calculate overshoot (startpool - indexptr) and subtract from end */
jeroen3 0:a04dc0c57d20 184 /* Since one element of overshoot results in end - 1 you would miss the last value */
jeroen3 0:a04dc0c57d20 185 c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
jeroen3 0:a04dc0c57d20 186 }
jeroen3 0:a04dc0c57d20 187 /* Read oldest buffer element */
jeroen3 0:a04dc0c57d20 188 { /* block with temporary variable to prevent stack use */
jeroen3 0:a04dc0c57d20 189 register uint32_t element;
jeroen3 0:a04dc0c57d20 190 /* Read to temp register */
jeroen3 0:a04dc0c57d20 191 element = *c->ptemp;
jeroen3 0:a04dc0c57d20 192 /* Empty */
jeroen3 0:a04dc0c57d20 193 *c->ptemp = 0;
jeroen3 0:a04dc0c57d20 194 /* Clear temp register */
jeroen3 0:a04dc0c57d20 195 c->temp = element;
jeroen3 0:a04dc0c57d20 196 }
jeroen3 0:a04dc0c57d20 197 /* Reduce elementcount */
jeroen3 0:a04dc0c57d20 198 c->elementcount--;
jeroen3 0:a04dc0c57d20 199 /* Check full flag */
jeroen3 0:a04dc0c57d20 200 if(c->elementcount < c->size)
jeroen3 0:a04dc0c57d20 201 c->full = 0;
jeroen3 0:a04dc0c57d20 202 return c->temp;
jeroen3 0:a04dc0c57d20 203 }
jeroen3 0:a04dc0c57d20 204
jeroen3 0:a04dc0c57d20 205 /**
jeroen3 0:a04dc0c57d20 206 * @brief Write to buffer
jeroen3 0:a04dc0c57d20 207 *
jeroen3 0:a04dc0c57d20 208 * @note Readpointer is automatically set to the last added element.
jeroen3 0:a04dc0c57d20 209 *
jeroen3 0:a04dc0c57d20 210 * @warning Consider this opertaion as atomic!
jeroen3 0:a04dc0c57d20 211 *
jeroen3 0:a04dc0c57d20 212 * @details Adds a value to the buffer.
jeroen3 0:a04dc0c57d20 213 * Automatically overwrites oldest elements when full.
jeroen3 0:a04dc0c57d20 214 *
jeroen3 0:a04dc0c57d20 215 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 216 * @param[in] data Data to add to buffer
jeroen3 0:a04dc0c57d20 217 *
jeroen3 0:a04dc0c57d20 218 * @return Number of free buffer elements
jeroen3 0:a04dc0c57d20 219 */
jeroen3 0:a04dc0c57d20 220 uint32_t xifo_write(xifo_t *c, uint32_t data){
jeroen3 0:a04dc0c57d20 221 /* Write data */
jeroen3 0:a04dc0c57d20 222 *c->write = data;
jeroen3 0:a04dc0c57d20 223 /* Update read pointer to most recent element */
jeroen3 0:a04dc0c57d20 224 c->read = c->write;
jeroen3 0:a04dc0c57d20 225 /* Write pointer increment */
jeroen3 0:a04dc0c57d20 226 c->write += 1;
jeroen3 0:a04dc0c57d20 227 /* Validate pointer */
jeroen3 0:a04dc0c57d20 228 if( c->write > c->endpool){
jeroen3 0:a04dc0c57d20 229 /* We exceeded pool boundaries */
jeroen3 0:a04dc0c57d20 230 c->write = c->startpool;
jeroen3 0:a04dc0c57d20 231 }
jeroen3 0:a04dc0c57d20 232 /* Update elementcount */
jeroen3 0:a04dc0c57d20 233 c->elementcount++;
jeroen3 0:a04dc0c57d20 234 /* Verify full */
jeroen3 0:a04dc0c57d20 235 if( c->elementcount >= c->size ){
jeroen3 0:a04dc0c57d20 236 c->full = 1;
jeroen3 0:a04dc0c57d20 237 c->elementcount = c->size;
jeroen3 0:a04dc0c57d20 238 }
jeroen3 0:a04dc0c57d20 239 /* return free elements count */
jeroen3 0:a04dc0c57d20 240 return c->size - c->elementcount;
jeroen3 0:a04dc0c57d20 241 }
jeroen3 0:a04dc0c57d20 242
jeroen3 0:a04dc0c57d20 243 /**
jeroen3 0:a04dc0c57d20 244 * @brief Get buffer size
jeroen3 0:a04dc0c57d20 245 *
jeroen3 0:a04dc0c57d20 246 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 247 *
jeroen3 0:a04dc0c57d20 248 * @return Size of memory pool in elements
jeroen3 0:a04dc0c57d20 249 */
jeroen3 0:a04dc0c57d20 250 uint32_t xifo_get_size(xifo_t *c){
jeroen3 0:a04dc0c57d20 251 return c->size;
jeroen3 0:a04dc0c57d20 252 }
jeroen3 0:a04dc0c57d20 253
jeroen3 0:a04dc0c57d20 254 /**
jeroen3 0:a04dc0c57d20 255 * @brief Get number of used elements
jeroen3 0:a04dc0c57d20 256 *
jeroen3 0:a04dc0c57d20 257 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 258 *
jeroen3 0:a04dc0c57d20 259 * @return Number of used buffer elements
jeroen3 0:a04dc0c57d20 260 */
jeroen3 0:a04dc0c57d20 261 uint32_t xifo_get_used(xifo_t *c){
jeroen3 0:a04dc0c57d20 262 return c->elementcount;
jeroen3 0:a04dc0c57d20 263 }
jeroen3 0:a04dc0c57d20 264
jeroen3 0:a04dc0c57d20 265 /**
jeroen3 0:a04dc0c57d20 266 * @brief Get number of free elements
jeroen3 0:a04dc0c57d20 267 *
jeroen3 0:a04dc0c57d20 268 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 269 *
jeroen3 0:a04dc0c57d20 270 * @return Number of free elements
jeroen3 0:a04dc0c57d20 271 */
jeroen3 0:a04dc0c57d20 272 uint32_t xifo_get_free(xifo_t *c){
jeroen3 0:a04dc0c57d20 273 return c->size - c->elementcount;
jeroen3 0:a04dc0c57d20 274 }
jeroen3 0:a04dc0c57d20 275
jeroen3 0:a04dc0c57d20 276 /**
jeroen3 0:a04dc0c57d20 277 * @brief Get full flag
jeroen3 0:a04dc0c57d20 278 *
jeroen3 0:a04dc0c57d20 279 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 0:a04dc0c57d20 280 *
jeroen3 0:a04dc0c57d20 281 * @return 1 if full
jeroen3 0:a04dc0c57d20 282 */
jeroen3 0:a04dc0c57d20 283 uint32_t xifo_get_full(xifo_t *c){
jeroen3 0:a04dc0c57d20 284 return c->full;
jeroen3 0:a04dc0c57d20 285 }
jeroen3 0:a04dc0c57d20 286
jeroen3 0:a04dc0c57d20 287 /** @} */