Multi purpose buffer module.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers xIFO.cpp Source File

xIFO.cpp

00001 /**
00002  * @file    xifo.c
00003  * @brief   xifo circular buffer with <t>/8/16/32/64 bit elements
00004  * @details xifo supplies object oriented circular buffer with 8 bit size elements. \n
00005  *          To use either as FIFO (First In First Out) or as FILO (First In Last Out)
00006  *          You might want to rename this file is you are using a C compiler.
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 #include "xIFO.h"
00035 
00036 #if xIFO_USE_64BIT == TRUE
00037 /**
00038  * @brief   Initialize buffer object structure.
00039  *
00040  * @note    Does not clear memory pool.
00041  *
00042  * @param[in] c   Pointer to @p xifo64_t object used for configuration.
00043  * @param[in] s   Number of elements buffer can hold (size).
00044  * @param[in] sp  Start of pre-allocated memory pool.
00045  */
00046 void xifo64_init(xifo64_t *c, uint32_t s, uint64_t *sp){
00047     c->startpool        = sp;
00048     c->size             = s;
00049     c->endpool          = &sp[--s];
00050     c->full             = 0;
00051     c->count            = 0;
00052     c->read             = sp;
00053     c->write            = sp;
00054 }
00055 
00056 /**
00057  * @brief   Clear buffer memory pool
00058  *
00059  * @note    Must be used on initialised buffer object.
00060  *
00061  * @param[in] c   Pointer to @p xifo64_t object.
00062  */
00063 void xifo64_clear(xifo64_t *c){
00064     register uint64_t *ptemp = c->startpool;
00065     register uint32_t i = c->size;
00066     while(i--){
00067 
00068         *ptemp++ = 0;
00069     }
00070 }
00071 
00072 /**
00073  * @brief   Read from buffer (lr) Least Recent oriented (fifo)
00074  *
00075  * @note    Buffer state will be preserved
00076  *
00077  * @warning Consider this opertaion as atomic!
00078  *
00079  * @details Read n elements from the oldest element to the most recent.
00080  *                  As for index[0] the least recently added element is returned.
00081  *                  And for index[count] the most recent element is returned.
00082  *                  This makes it possible to peek in fifo.
00083  *
00084  * @param[in] c         Pointer to @p xifo64_t used for configuration.
00085  * @param[in] index   Index relative from least recent
00086  *
00087  * @return  Contents of element or 0 if failed (element can hold 0)
00088  */
00089 uint64_t xifo64_read_lr(xifo64_t *c, uint32_t index){
00090     register uint64_t *ptemp;
00091     /* Verify there is valid data to read */
00092     if(index >= c->count){
00093         return 0;   /* Nothing to read there */
00094     }
00095     /* Calculate index of oldest element */
00096     index = (c->count-1) - index;
00097     /* Set pointer */
00098     ptemp = (c->read) - index;
00099     if(ptemp < c->startpool){
00100         /* Exceeded pool boundaries */
00101         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00102         /* Since one element of overshoot results in end - 1 you would miss the last value */
00103         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00104     }
00105     /* Read most recent */
00106     return *ptemp;
00107 }
00108 
00109 /**
00110  * @brief   Read from buffer (mr) Most Recent oriented (filo)
00111  *
00112  * @note    Buffer state will be preserved
00113  *
00114  * @warning Consider this opertaion as atomic!
00115  *
00116  * @details Read n elements back in time.
00117  *                  As for index[0] the most recently added element is returned.
00118  *                  And for index[count] the oldest element is returned.
00119  *                  This makes it possible to keep history. For DSP application.
00120  *
00121  * @param[in] c         Pointer to @p xifo64_t used for configuration.
00122  * @param[in] index   Index relative from most recent
00123  *
00124  * @return  Contents of element or 0 if failed (element can hold 0)
00125  */
00126 uint64_t xifo64_read_mr(xifo64_t *c, uint32_t index){
00127     register uint64_t *ptemp;
00128     /* Verify there is valid data to read */
00129     if(index >= c->count){
00130         return 0;   /* Nothing to read there */
00131     }
00132     /* Set pointer */
00133     ptemp = (c->read) - index;
00134     /* Validate pointer */
00135     if(ptemp < c->startpool){
00136         /* Exceeded pool boundaries */
00137         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00138         /* Since one element of overshoot results in end - 1 you would miss the last value */
00139         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00140     }
00141     /* Read most recent */
00142     return *ptemp;
00143 }
00144 
00145 /**
00146  * @brief   Pop (mr) most recent from buffer (filo)
00147  *
00148  * @note    Buffer state will be altered
00149  *
00150  * @warning Consider this opertaion as atomic!
00151  *
00152  * @details Read and remove the most recently added from the buffer.
00153  *                  Using this results in a stack type of buffer.
00154  *
00155  * @param[in] c         Pointer to @p xifo64_t used for configuration.
00156  *
00157  * @return  Contents of element or 0 if failed (element can hold 0)
00158  */
00159 uint64_t xifo64_pop_mr(xifo64_t *c){
00160     register uint64_t temp;
00161     /* Verify there is valid data read */
00162     if(c->count == 0){
00163         return 0;   /* Nothing to read there */
00164     }
00165     /* Read */
00166     temp = *c->read;
00167     /* Empty */
00168     *c->read = 0;
00169     /* Most recent element read, return write pointer */
00170     c->write = c->read;
00171     /* Decrement read pointer */
00172     c->read--;
00173     /* Validate pointer */
00174     if( c->read < c->startpool ){
00175         /* Exceeded pool boundaries */
00176         c->read = c->endpool;
00177     }
00178     /* Reduce count */
00179     c->count--;
00180     if(c->count < c->size)
00181         c->full = 0;
00182     return temp;
00183 }
00184 
00185 /**
00186  * @brief   Pop (lr) least recent from buffer (fifo)
00187  *
00188  * @note    Buffer state will be altered
00189  *
00190  * @warning Consider this opertaion as atomic!
00191  *
00192  * @details Read and remove the least recently added from the buffer.
00193  *                  Using this results in a fifo type of buffer.
00194  *
00195  * @param[in] c Pointer to @p xifo64_t used for configuration.
00196  *
00197  * @return  Contents of element or 0 if failed (element can hold 0)
00198  */
00199 uint64_t xifo64_pop_lr(xifo64_t *c){
00200     register uint64_t *ptemp;
00201     register uint64_t temp;
00202     /* Verify there is valid data read */
00203     if(c->count == 0){
00204         return 0;   /* Nothing to read there */
00205     }
00206     /* Derive least recent buffer element */
00207     ptemp = (c->read+1) - c->count;
00208     /* Validate pointer */
00209     if(ptemp < c->startpool){
00210         /* Exceeded pool boundaries */
00211         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00212         /* Since one element of overshoot results in end - 1 you would miss the last value */
00213         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00214     }
00215     /* Read oldest buffer element */
00216     /* Read to temp register */
00217     temp = *ptemp;
00218     /* Empty buffer element */
00219     *ptemp = 0;
00220     /* Reduce count */
00221     c->count--;
00222     /* Check full flag */
00223     if(c->count < c->size)
00224         c->full = 0;
00225     return temp;
00226 }
00227 
00228 /**
00229  * @brief   Write to buffer
00230  *
00231  * @note    Readpointer is automatically set to the last added element.
00232  *
00233  * @warning Consider this opertaion as atomic!
00234  *
00235  * @details Adds a value to the buffer.
00236  *                  Automatically overwrites oldest elements when full.
00237  *
00238  * @param[in] c         Pointer to @p xifo64_t used for configuration.
00239  * @param[in] data  Data to add to buffer
00240  *
00241  * @return  Number of free buffer elements
00242  */
00243 uint32_t xifo64_write(xifo64_t *c, uint64_t data){
00244     /* Write data */
00245     *c->write = data;
00246     /* Update read pointer to most recent element */
00247     c->read = c->write;
00248     /* Write pointer increment */
00249     c->write++;
00250     /* Validate pointer */
00251     if( c->write > c->endpool){
00252         /* We exceeded pool boundaries */
00253         c->write = c->startpool;
00254     }
00255     /* Update count */
00256     c->count++;
00257     /* Verify full */
00258     if( c->count >= c->size ){
00259         c->full = 1;
00260         c->count = c->size;
00261     }
00262     /* return free elements count */
00263     return c->size - c->count;
00264 }
00265 
00266 /**
00267  * @brief   Get buffer size
00268  *
00269  * @param[in] c Pointer to @p xifo64_t used for configuration.
00270  *
00271  * @return  Size of memory pool in elements
00272  */
00273 uint32_t xifo64_get_size(xifo64_t *c){
00274     return c->size;
00275 }
00276 
00277 /**
00278  * @brief   Get number of used elements
00279  *
00280  * @param[in] c Pointer to @p xifo64_t used for configuration.
00281  *
00282  * @return  Number of used buffer elements
00283  */
00284 uint32_t xifo64_get_used(xifo64_t *c){
00285     return c->count;
00286 }
00287 
00288 /**
00289 * @brief   Get number of free elements
00290 *
00291 * @param[in] c  Pointer to @p xifo64_t used for configuration.
00292 *
00293 * @return   Number of free elements
00294 */
00295 uint32_t xifo64_get_free(xifo64_t *c){
00296     return c->size - c->count;
00297 }
00298 
00299 /**
00300  * @brief   Get full flag
00301  *
00302  * @param[in] c Pointer to @p xifo64_t used for configuration.
00303  *
00304  * @return  1 if full
00305  */
00306 uint32_t xifo64_get_full(xifo64_t *c){
00307     return c->full;
00308 }
00309 
00310 /** @} */
00311 #endif
00312 
00313 #if xIFO_USE_32BIT == TRUE
00314 /**
00315  * @brief   Initialize buffer object structure.
00316  *
00317  * @note    Does not clear memory pool.
00318  *
00319  * @param[in] c   Pointer to @p xifo32_t object used for configuration.
00320  * @param[in] s   Number of elements buffer can hold (size).
00321  * @param[in] sp  Start of pre-allocated memory pool.
00322  */
00323 void xifo32_init(xifo32_t *c, uint32_t s, uint32_t *sp){
00324     c->startpool        = sp;
00325     c->size             = s;
00326     c->endpool          = &sp[--s];
00327     c->full             = 0;
00328     c->count            = 0;
00329     c->read             = sp;
00330     c->write            = sp;
00331 }
00332 
00333 /**
00334  * @brief   Clear buffer memory pool
00335  *
00336  * @note    Must be used on initialised buffer object.
00337  *
00338  * @param[in] c   Pointer to @p xifo32_t object.
00339  */
00340 void xifo32_clear(xifo32_t *c){
00341     register uint32_t *ptemp = c->startpool;
00342     register uint32_t i = c->size;
00343     while(i--){
00344         *ptemp++ = 0;
00345     }
00346 }
00347 
00348 /**
00349  * @brief   Read from buffer (lr) Least Recent oriented (fifo)
00350  *
00351  * @note    Buffer state will be preserved
00352  *
00353  * @warning Consider this opertaion as atomic!
00354  *
00355  * @details Read n elements from the oldest element to the most recent.
00356  *                  As for index[0] the least recently added element is returned.
00357  *                  And for index[count] the most recent element is returned.
00358  *                  This makes it possible to peek in fifo.
00359  *
00360  * @param[in] c         Pointer to @p xifo32_t used for configuration.
00361  * @param[in] index   Index relative from least recent
00362  *
00363  * @return  Contents of element or 0 if failed (element can hold 0)
00364  */
00365 uint32_t xifo32_read_lr(xifo32_t *c, uint32_t index){
00366     register uint32_t *ptemp;
00367     /* Verify there is valid data to read */
00368     if(index >= c->count){
00369         return 0;   /* Nothing to read there */
00370     }
00371     /* Calculate index of oldest element */
00372     index = (c->count-1) - index;
00373     /* Set pointer */
00374     ptemp = (c->read) - index;
00375     if(ptemp < c->startpool){
00376         /* Exceeded pool boundaries */
00377         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00378         /* Since one element of overshoot results in end - 1 you would miss the last value */
00379         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00380     }
00381     /* Read most recent */
00382     return *ptemp;
00383 }
00384 
00385 /**
00386  * @brief   Read from buffer (mr) Most Recent oriented (filo)
00387  *
00388  * @note    Buffer state will be preserved
00389  *
00390  * @warning Consider this opertaion as atomic!
00391  *
00392  * @details Read n elements back in time.
00393  *                  As for index[0] the most recently added element is returned.
00394  *                  And for index[count] the oldest element is returned.
00395  *                  This makes it possible to keep history. For DSP application.
00396  *
00397  * @param[in] c         Pointer to @p xifo32_t used for configuration.
00398  * @param[in] index   Index relative from most recent
00399  *
00400  * @return  Contents of element or 0 if failed (element can hold 0)
00401  */
00402 uint32_t xifo32_read_mr(xifo32_t *c, uint32_t index){
00403     register uint32_t *ptemp;
00404     /* Verify there is valid data to read */
00405     if(index >= c->count){
00406         return 0;   /* Nothing to read there */
00407     }
00408     /* Set pointer */
00409     ptemp = (c->read) - index;
00410     /* Validate pointer */
00411     if(ptemp < c->startpool){
00412         /* Exceeded pool boundaries */
00413         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00414         /* Since one element of overshoot results in end - 1 you would miss the last value */
00415         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00416     }
00417     /* Read most recent */
00418     return *ptemp;
00419 }
00420 
00421 /**
00422  * @brief   Pop (mr) most recent from buffer (filo)
00423  *
00424  * @note    Buffer state will be altered
00425  *
00426  * @warning Consider this opertaion as atomic!
00427  *
00428  * @details Read and remove the most recently added from the buffer.
00429  *                  Using this results in a stack type of buffer.
00430  *
00431  * @param[in] c         Pointer to @p xifo32_t used for configuration.
00432  *
00433  * @return  Contents of element or 0 if failed (element can hold 0)
00434  */
00435 uint32_t xifo32_pop_mr(xifo32_t *c){
00436     register uint32_t temp;
00437     /* Verify there is valid data read */
00438     if(c->count == 0){
00439         return 0;   /* Nothing to read there */
00440     }
00441     /* Read */
00442     temp = *c->read;
00443     /* Empty */
00444     *c->read = 0;
00445     /* Most recent element read, return write pointer */
00446     c->write = c->read;
00447     /* Decrement read pointer */
00448     c->read--;
00449     /* Validate pointer */
00450     if( c->read < c->startpool ){
00451         /* Exceeded pool boundaries */
00452         c->read = c->endpool;
00453     }
00454     /* Reduce count */
00455     c->count--;
00456     if(c->count < c->size)
00457         c->full = 0;
00458     return temp;
00459 }
00460 
00461 /**
00462  * @brief   Pop (lr) least recent from buffer (fifo)
00463  *
00464  * @note    Buffer state will be altered
00465  *
00466  * @warning Consider this opertaion as atomic!
00467  *
00468  * @details Read and remove the least recently added from the buffer.
00469  *                  Using this results in a fifo type of buffer.
00470  *
00471  * @param[in] c Pointer to @p xifo32_t used for configuration.
00472  *
00473  * @return  Contents of element or 0 if failed (element can hold 0)
00474  */
00475 uint32_t xifo32_pop_lr(xifo32_t *c){
00476     register uint32_t *ptemp;
00477     register uint32_t temp;
00478     /* Verify there is valid data read */
00479     if(c->count == 0){
00480         return 0;   /* Nothing to read there */
00481     }
00482     /* Derive least recent buffer element */
00483     ptemp = (c->read+1) - c->count;
00484     /* Validate pointer */
00485     if(ptemp < c->startpool){
00486         /* Exceeded pool boundaries */
00487         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00488         /* Since one element of overshoot results in end - 1 you would miss the last value */
00489         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00490     }
00491     /* Read oldest buffer element */
00492     /* Read to temp register */
00493     temp = *ptemp;
00494     /* Empty buffer element */
00495     *ptemp = 0;
00496     /* Reduce count */
00497     c->count--;
00498     /* Check full flag */
00499     if(c->count < c->size)
00500         c->full = 0;
00501     return temp;
00502 }
00503 
00504 /**
00505  * @brief   Write to buffer
00506  *
00507  * @note    Readpointer is automatically set to the last added element.
00508  *
00509  * @warning Consider this opertaion as atomic!
00510  *
00511  * @details Adds a value to the buffer.
00512  *                  Automatically overwrites oldest elements when full.
00513  *
00514  * @param[in] c         Pointer to @p xifo32_t used for configuration.
00515  * @param[in] data  Data to add to buffer
00516  *
00517  * @return  Number of free buffer elements
00518  */
00519 uint32_t xifo32_write(xifo32_t *c, uint32_t data){
00520     /* Write data */
00521     *c->write = data;
00522     /* Update read pointer to most recent element */
00523     c->read = c->write;
00524     /* Write pointer increment */
00525     c->write++;
00526     /* Validate pointer */
00527     if( c->write > c->endpool){
00528         /* We exceeded pool boundaries */
00529         c->write = c->startpool;
00530     }
00531     /* Update count */
00532     c->count++;
00533     /* Verify full */
00534     if( c->count >= c->size ){
00535         c->full = 1;
00536         c->count = c->size;
00537     }
00538     /* return free elements count */
00539     return c->size - c->count;
00540 }
00541 
00542 /**
00543  * @brief   Get buffer size
00544  *
00545  * @param[in] c Pointer to @p xifo32_t used for configuration.
00546  *
00547  * @return  Size of memory pool in elements
00548  */
00549 uint32_t xifo32_get_size(xifo32_t *c){
00550     return c->size;
00551 }
00552 
00553 /**
00554  * @brief   Get number of used elements
00555  *
00556  * @param[in] c Pointer to @p xifo32_t used for configuration.
00557  *
00558  * @return  Number of used buffer elements
00559  */
00560 uint32_t xifo32_get_used(xifo32_t *c){
00561     return c->count;
00562 }
00563 
00564 /**
00565 * @brief   Get number of free elements
00566 *
00567 * @param[in] c  Pointer to @p xifo32_t used for configuration.
00568 *
00569 * @return   Number of free elements
00570 */
00571 uint32_t xifo32_get_free(xifo32_t *c){
00572     return c->size - c->count;
00573 }
00574 
00575 /**
00576  * @brief   Get full flag
00577  *
00578  * @param[in] c Pointer to @p xifo32_t used for configuration.
00579  *
00580  * @return  1 if full
00581  */
00582 uint32_t xifo32_get_full(xifo32_t *c){
00583     return c->full;
00584 }
00585 
00586 /** @} */
00587 #endif
00588 
00589 #if xIFO_USE_16BIT == TRUE
00590 /**
00591  * @brief   Initialize buffer object structure.
00592  *
00593  * @note    Does not clear memory pool.
00594  *
00595  * @param[in] c   Pointer to @p xifo16_t object used for configuration.
00596  * @param[in] s   Number of elements buffer can hold (size).
00597  * @param[in] sp  Start of pre-allocated memory pool.
00598  */
00599 void xifo16_init(xifo16_t *c, uint32_t s, uint16_t *sp){
00600     c->startpool        = sp;
00601     c->size             = s;
00602     c->endpool          = &sp[--s];
00603     c->full             = 0;
00604     c->count            = 0;
00605     c->read             = sp;
00606     c->write            = sp;
00607 }
00608 
00609 /**
00610  * @brief   Clear buffer memory pool
00611  *
00612  * @note    Must be used on initialised buffer object.
00613  *
00614  * @param[in] c   Pointer to @p xifo16_t object.
00615  */
00616 void xifo16_clear(xifo16_t *c){
00617     register uint16_t *ptemp = c->startpool;
00618     register uint32_t i = c->size;
00619     while(i--){
00620         *ptemp++ = 0;
00621     }
00622 }
00623 
00624 /**
00625  * @brief   Read from buffer (lr) Least Recent oriented (fifo)
00626  *
00627  * @note    Buffer state will be preserved
00628  *
00629  * @warning Consider this opertaion as atomic!
00630  *
00631  * @details Read n elements from the oldest element to the most recent.
00632  *                  As for index[0] the least recently added element is returned.
00633  *                  And for index[count] the most recent element is returned.
00634  *                  This makes it possible to peek in fifo.
00635  *
00636  * @param[in] c         Pointer to @p xifo16_t used for configuration.
00637  * @param[in] index   Index relative from least recent
00638  *
00639  * @return  Contents of element or 0 if failed (element can hold 0)
00640  */
00641 uint16_t xifo16_read_lr(xifo16_t *c, uint32_t index){
00642     register uint16_t *ptemp;
00643     /* Verify there is valid data to read */
00644     if(index >= c->count){
00645         return 0;   /* Nothing to read there */
00646     }
00647     /* Calculate index of oldest element */
00648     index = (c->count-1) - index;
00649     /* Set pointer */
00650     ptemp = (c->read) - index;
00651     if(ptemp < c->startpool){
00652         /* Exceeded pool boundaries */
00653         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00654         /* Since one element of overshoot results in end - 1 you would miss the last value */
00655         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00656     }
00657     /* Read most recent */
00658     return *ptemp;
00659 }
00660 
00661 /**
00662  * @brief   Read from buffer (mr) Most Recent oriented (filo)
00663  *
00664  * @note    Buffer state will be preserved
00665  *
00666  * @warning Consider this opertaion as atomic!
00667  *
00668  * @details Read n elements back in time.
00669  *                  As for index[0] the most recently added element is returned.
00670  *                  And for index[count] the oldest element is returned.
00671  *                  This makes it possible to keep history. For DSP application.
00672  *
00673  * @param[in] c         Pointer to @p xifo16_t used for configuration.
00674  * @param[in] index   Index relative from most recent
00675  *
00676  * @return  Contents of element or 0 if failed (element can hold 0)
00677  */
00678 uint16_t xifo16_read_mr(xifo16_t *c, uint32_t index){
00679     register uint16_t *ptemp;
00680     /* Verify there is valid data to read */
00681     if(index >= c->count){
00682         return 0;   /* Nothing to read there */
00683     }
00684     /* Set pointer */
00685     ptemp = (c->read) - index;
00686     /* Validate pointer */
00687     if(ptemp < c->startpool){
00688         /* Exceeded pool boundaries */
00689         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00690         /* Since one element of overshoot results in end - 1 you would miss the last value */
00691         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00692     }
00693     /* Read most recent */
00694     return *ptemp;
00695 }
00696 
00697 /**
00698  * @brief   Pop (mr) most recent from buffer (filo)
00699  *
00700  * @note    Buffer state will be altered
00701  *
00702  * @warning Consider this opertaion as atomic!
00703  *
00704  * @details Read and remove the most recently added from the buffer.
00705  *                  Using this results in a stack type of buffer.
00706  *
00707  * @param[in] c         Pointer to @p xifo16_t used for configuration.
00708  *
00709  * @return  Contents of element or 0 if failed (element can hold 0)
00710  */
00711 uint16_t xifo16_pop_mr(xifo16_t *c){
00712     register uint16_t temp;
00713     /* Verify there is valid data read */
00714     if(c->count == 0){
00715         return 0;   /* Nothing to read there */
00716     }
00717     /* Read */
00718     temp = *c->read;
00719     /* Empty */
00720     *c->read = 0;
00721     /* Most recent element read, return write pointer */
00722     c->write = c->read;
00723     /* Decrement read pointer */
00724     c->read--;
00725     /* Validate pointer */
00726     if( c->read < c->startpool ){
00727         /* Exceeded pool boundaries */
00728         c->read = c->endpool;
00729     }
00730     /* Reduce count */
00731     c->count--;
00732     if(c->count < c->size)
00733         c->full = 0;
00734     return temp;
00735 }
00736 
00737 /**
00738  * @brief   Pop (lr) least recent from buffer (fifo)
00739  *
00740  * @note    Buffer state will be altered
00741  *
00742  * @warning Consider this opertaion as atomic!
00743  *
00744  * @details Read and remove the least recently added from the buffer.
00745  *                  Using this results in a fifo type of buffer.
00746  *
00747  * @param[in] c Pointer to @p xifo16_t used for configuration.
00748  *
00749  * @return  Contents of element or 0 if failed (element can hold 0)
00750  */
00751 uint16_t xifo16_pop_lr(xifo16_t *c){
00752     register uint16_t *ptemp;
00753     register uint16_t temp;
00754     /* Verify there is valid data read */
00755     if(c->count == 0){
00756         return 0;   /* Nothing to read there */
00757     }
00758     /* Derive least recent buffer element */
00759     ptemp = (c->read+1) - c->count;
00760     /* Validate pointer */
00761     if(ptemp < c->startpool){
00762         /* Exceeded pool boundaries */
00763         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00764         /* Since one element of overshoot results in end - 1 you would miss the last value */
00765         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00766     }
00767     /* Read oldest buffer element */
00768     /* Read to temp register */
00769     temp = *ptemp;
00770     /* Empty buffer element */
00771     *ptemp = 0;
00772     /* Reduce count */
00773     c->count--;
00774     /* Check full flag */
00775     if(c->count < c->size)
00776         c->full = 0;
00777     return temp;
00778 }
00779 
00780 /**
00781  * @brief   Write to buffer
00782  *
00783  * @note    Readpointer is automatically set to the last added element.
00784  *
00785  * @warning Consider this opertaion as atomic!
00786  *
00787  * @details Adds a value to the buffer.
00788  *                  Automatically overwrites oldest elements when full.
00789  *
00790  * @param[in] c         Pointer to @p xifo16_t used for configuration.
00791  * @param[in] data  Data to add to buffer
00792  *
00793  * @return  Number of free buffer elements
00794  */
00795 uint32_t xifo16_write(xifo16_t *c, uint16_t data){
00796     /* Write data */
00797     *c->write = data;
00798     /* Update read pointer to most recent element */
00799     c->read = c->write;
00800     /* Write pointer increment */
00801     c->write++;
00802     /* Validate pointer */
00803     if( c->write > c->endpool){
00804         /* We exceeded pool boundaries */
00805         c->write = c->startpool;
00806     }
00807     /* Update count */
00808     c->count++;
00809     /* Verify full */
00810     if( c->count >= c->size ){
00811         c->full = 1;
00812         c->count = c->size;
00813     }
00814     /* return free elements count */
00815     return c->size - c->count;
00816 }
00817 
00818 /**
00819  * @brief   Get buffer size
00820  *
00821  * @param[in] c Pointer to @p xifo16_t used for configuration.
00822  *
00823  * @return  Size of memory pool in elements
00824  */
00825 uint32_t xifo16_get_size(xifo16_t *c){
00826     return c->size;
00827 }
00828 
00829 /**
00830  * @brief   Get number of used elements
00831  *
00832  * @param[in] c Pointer to @p xifo16_t used for configuration.
00833  *
00834  * @return  Number of used buffer elements
00835  */
00836 uint32_t xifo16_get_used(xifo16_t *c){
00837     return c->count;
00838 }
00839 
00840 /**
00841 * @brief   Get number of free elements
00842 *
00843 * @param[in] c  Pointer to @p xifo16_t used for configuration.
00844 *
00845 * @return   Number of free elements
00846 */
00847 uint32_t xifo16_get_free(xifo16_t *c){
00848     return c->size - c->count;
00849 }
00850 
00851 /**
00852  * @brief   Get full flag
00853  *
00854  * @param[in] c Pointer to @p xifo16_t used for configuration.
00855  *
00856  * @return  1 if full
00857  */
00858 uint32_t xifo16_get_full(xifo16_t *c){
00859     return c->full;
00860 }
00861 
00862 /** @} */
00863 
00864 #endif
00865 
00866 #if xIFO_USE_8BIT == TRUE
00867 /**
00868  * @brief   Initialize buffer object structure.
00869  *
00870  * @note    Does not clear memory pool.
00871  *
00872  * @param[in] c   Pointer to @p xifo8_t object used for configuration.
00873  * @param[in] s   Number of elements buffer can hold (size).
00874  * @param[in] sp  Start of pre-allocated memory pool.
00875  */
00876 void xifo8_init(xifo8_t *c, uint32_t s, uint8_t *sp){
00877     c->startpool        = sp;
00878     c->size             = s;
00879     c->endpool          = &sp[--s];
00880     c->full             = 0;
00881     c->count            = 0;
00882     c->read             = sp;
00883     c->write            = sp;
00884 }
00885 
00886 /**
00887  * @brief   Clear buffer memory pool
00888  *
00889  * @note    Must be used on initialised buffer object.
00890  *
00891  * @param[in] c   Pointer to @p xifo8_t object.
00892  */
00893 void xifo8_clear(xifo8_t *c){
00894     register uint8_t *ptemp = c->startpool;
00895     register uint32_t i = c->size;
00896     while(i--){
00897         *ptemp++ = 0;
00898     }
00899 }
00900 
00901 /**
00902  * @brief   Read from buffer (lr) Least Recent oriented (fifo)
00903  *
00904  * @note    Buffer state will be preserved
00905  *
00906  * @warning Consider this opertaion as atomic!
00907  *
00908  * @details Read n elements from the oldest element to the most recent.
00909  *                  As for index[0] the least recently added element is returned.
00910  *                  And for index[count] the most recent element is returned.
00911  *                  This makes it possible to peek in fifo.
00912  *
00913  * @param[in] c         Pointer to @p xifo8_t used for configuration.
00914  * @param[in] index   Index relative from least recent
00915  *
00916  * @return  Contents of element or 0 if failed (element can hold 0)
00917  */
00918 uint8_t xifo8_read_lr(xifo8_t *c, uint32_t index){
00919     register uint8_t *ptemp;
00920     /* Verify there is valid data to read */
00921     if(index >= c->count){
00922         return 0;   /* Nothing to read there */
00923     }
00924     /* Calculate index of oldest element */
00925     index = (c->count-1) - index;
00926     /* Set pointer */
00927     ptemp = (c->read) - index;
00928     if(ptemp < c->startpool){
00929         /* Exceeded pool boundaries */
00930         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00931         /* Since one element of overshoot results in end - 1 you would miss the last value */
00932         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00933     }
00934     /* Read most recent */
00935     return *ptemp;
00936 }
00937 
00938 /**
00939  * @brief   Read from buffer (mr) Most Recent oriented (filo)
00940  *
00941  * @note    Buffer state will be preserved
00942  *
00943  * @warning Consider this opertaion as atomic!
00944  *
00945  * @details Read n elements back in time.
00946  *                  As for index[0] the most recently added element is returned.
00947  *                  And for index[count] the oldest element is returned.
00948  *                  This makes it possible to keep history. For DSP application.
00949  *
00950  * @param[in] c         Pointer to @p xifo8_t used for configuration.
00951  * @param[in] index   Index relative from most recent
00952  *
00953  * @return  Contents of element or 0 if failed (element can hold 0)
00954  */
00955 uint8_t xifo8_read_mr(xifo8_t *c, uint32_t index){
00956     register uint8_t *ptemp;
00957     /* Verify there is valid data to read */
00958     if(index >= c->count){
00959         return 0;   /* Nothing to read there */
00960     }
00961     /* Set pointer */
00962     ptemp = (c->read) - index;
00963     /* Validate pointer */
00964     if(ptemp < c->startpool){
00965         /* Exceeded pool boundaries */
00966         /* Calculate overshoot (startpool - indexptr) and subtract from end */
00967         /* Since one element of overshoot results in end - 1 you would miss the last value */
00968         ptemp = (c->endpool+1) - (c->startpool - ptemp);
00969     }
00970     /* Read most recent */
00971     return *ptemp;
00972 }
00973 
00974 /**
00975  * @brief   Pop (mr) most recent from buffer (filo)
00976  *
00977  * @note    Buffer state will be altered
00978  *
00979  * @warning Consider this opertaion as atomic!
00980  *
00981  * @details Read and remove the most recently added from the buffer.
00982  *                  Using this results in a stack type of buffer.
00983  *
00984  * @param[in] c         Pointer to @p xifo8_t used for configuration.
00985  *
00986  * @return  Contents of element or 0 if failed (element can hold 0)
00987  */
00988 uint8_t xifo8_pop_mr(xifo8_t *c){
00989     register uint8_t temp;
00990     /* Verify there is valid data read */
00991     if(c->count == 0){
00992         return 0;   /* Nothing to read there */
00993     }
00994     /* Read */
00995     temp = *c->read;
00996     /* Empty */
00997     *c->read = 0;
00998     /* Most recent element read, return write pointer */
00999     c->write = c->read;
01000     /* Decrement read pointer */
01001     c->read--;
01002     /* Validate pointer */
01003     if( c->read < c->startpool ){
01004         /* Exceeded pool boundaries */
01005         c->read = c->endpool;
01006     }
01007     /* Reduce count */
01008     c->count--;
01009     if(c->count < c->size)
01010         c->full = 0;
01011     return temp;
01012 }
01013 
01014 /**
01015  * @brief   Pop (lr) least recent from buffer (fifo)
01016  *
01017  * @note    Buffer state will be altered
01018  *
01019  * @warning Consider this opertaion as atomic!
01020  *
01021  * @details Read and remove the least recently added from the buffer.
01022  *                  Using this results in a fifo type of buffer.
01023  *
01024  * @param[in] c Pointer to @p xifo8_t used for configuration.
01025  *
01026  * @return  Contents of element or 0 if failed (element can hold 0)
01027  */
01028 uint8_t xifo8_pop_lr(xifo8_t *c){
01029     register uint8_t *ptemp;
01030     register uint8_t temp;
01031     /* Verify there is valid data read */
01032     if(c->count == 0){
01033         return 0;   /* Nothing to read there */
01034     }
01035     /* Derive least recent buffer element */
01036     ptemp = (c->read+1) - c->count;
01037     /* Validate pointer */
01038     if(ptemp < c->startpool){
01039         /* Exceeded pool boundaries */
01040         /* Calculate overshoot (startpool - indexptr) and subtract from end */
01041         /* Since one element of overshoot results in end - 1 you would miss the last value */
01042         ptemp = (c->endpool+1) - (c->startpool - ptemp);
01043     }
01044     /* Read oldest buffer element */
01045     /* Read to temp register */
01046     temp = *ptemp;
01047     /* Empty buffer element */
01048     *ptemp = 0;
01049     /* Reduce count */
01050     c->count--;
01051     /* Check full flag */
01052     if(c->count < c->size)
01053         c->full = 0;
01054     return temp;
01055 }
01056 
01057 /**
01058  * @brief   Write to buffer
01059  *
01060  * @note    Readpointer is automatically set to the last added element.
01061  *
01062  * @warning Consider this opertaion as atomic!
01063  *
01064  * @details Adds a value to the buffer.
01065  *                  Automatically overwrites oldest elements when full.
01066  *
01067  * @param[in] c         Pointer to @p xifo8_t used for configuration.
01068  * @param[in] data  Data to add to buffer
01069  *
01070  * @return  Number of free buffer elements
01071  */
01072 uint32_t xifo8_write(xifo8_t *c, uint8_t data){
01073     /* Write data */
01074     *c->write = data;
01075     /* Update read pointer to most recent element */
01076     c->read = c->write;
01077     /* Write pointer increment */
01078     c->write++;
01079     /* Validate pointer */
01080     if( c->write > c->endpool){
01081         /* We exceeded pool boundaries */
01082         c->write = c->startpool;
01083     }
01084     /* Update count */
01085     c->count++;
01086     /* Verify full */
01087     if( c->count >= c->size ){
01088         c->full = 1;
01089         c->count = c->size;
01090     }
01091     /* return free elements count */
01092     return c->size - c->count;
01093 }
01094 
01095 /**
01096  * @brief   Get buffer size
01097  *
01098  * @param[in] c Pointer to @p xifo8_t used for configuration.
01099  *
01100  * @return  Size of memory pool in elements
01101  */
01102 uint32_t xifo8_get_size(xifo8_t *c){
01103     return c->size;
01104 }
01105 
01106 /**
01107  * @brief   Get number of used elements
01108  *
01109  * @param[in] c Pointer to @p xifo8_t used for configuration.
01110  *
01111  * @return  Number of used buffer elements
01112  */
01113 uint32_t xifo8_get_used(xifo8_t *c){
01114     return c->count;
01115 }
01116 
01117 /**
01118 * @brief   Get number of free elements
01119 *
01120 * @param[in] c  Pointer to @p xifo8_t used for configuration.
01121 *
01122 * @return   Number of free elements
01123 */
01124 uint32_t xifo8_get_free(xifo8_t *c){
01125     return c->size - c->count;
01126 }
01127 
01128 /**
01129  * @brief   Get full flag
01130  *
01131  * @param[in] c Pointer to @p xifo8_t used for configuration.
01132  *
01133  * @return  1 if full
01134  */
01135 uint32_t xifo8_get_full(xifo8_t *c){
01136     return c->full;
01137 }
01138 
01139 /** @} */
01140 #endif
01141 
01142 /** @} */