LightweightRingBuff.h 7.46 KB
 Dean Camera committed Jun 06, 2010 1 2 3 /* LUFA Library Copyright (C) Dean Camera, 2010.  4   Dean Camera committed Jun 06, 2010 5  dean [at] fourwalledcubicle [dot] com  Dean Camera committed Oct 28, 2010 6  www.lufa-lib.org  Dean Camera committed Jun 06, 2010 7 8 9 10 11 */ /* Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)  12  Permission to use, copy, modify, distribute, and sell this  Dean Camera committed Jun 06, 2010 13  software and its documentation for any purpose is hereby granted  14  without fee, provided that the above copyright notice appear in  Dean Camera committed Jun 06, 2010 15  all copies and that both that the copyright notice and this  16 17 18  permission notice and warranty disclaimer appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the  Dean Camera committed Jun 06, 2010 19 20 21 22 23 24 25 26 27 28 29 30 31 32  software without specific, written prior permission. The author disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ /** \file *  Dean Camera committed Aug 29, 2010 33 34 35 36 37 38 39 40  * Ultra lightweight ring buffer, for fast insertion/deletion. This uses inlined functions * for maximum speed. All buffers created with this library must be of the same size, however * multiple independant buffers can be created. * * Note that for each buffer, insertion and removal operations may occur at the same time (via * a multithreaded ISR based system) however the same kind of operation (two or more insertions * or deletions) must not overlap. If there is possibility of two or more of the same kind of * operating occuring at the same point in time, atomic (mutex) locking should be used.  Dean Camera committed Jun 06, 2010 41  */  42   Dean Camera committed Jun 06, 2010 43 44 45 46 #ifndef _ULW_RING_BUFF_H_ #define _ULW_RING_BUFF_H_ /* Includes: */  Dean Camera committed Jun 06, 2010 47  #include  48   Dean Camera committed Jun 06, 2010 49 50 51 52  #include #include /* Defines: */  Dean Camera committed Jun 06, 2010 53  /** Size of each ring buffer, in data elements - must be between 1 and 255. */  Dean Camera committed Nov 21, 2010 54  #define BUFFER_SIZE 128  55   Dean Camera committed Jun 06, 2010 56  /** Type of data to store into the buffer. */  Dean Camera committed Aug 01, 2010 57 58 59 60 61 62 63 64 65 66  #define RingBuff_Data_t uint8_t /** Datatype which may be used to store the count of data stored in a buffer, retrieved * via a call to \ref RingBuffer_GetCount(). */ #if (BUFFER_SIZE <= 0xFF) #define RingBuff_Count_t uint8_t #else #define RingBuff_Count_t uint16_t #endif  Dean Camera committed Jun 06, 2010 67 68  /* Type Defines: */  Dean Camera committed Jun 06, 2010 69 70 71  /** Type define for a new ring buffer object. Buffers should be initialized via a call to * \ref RingBuffer_InitBuffer() before use. */  Dean Camera committed Jun 06, 2010 72 73  typedef struct {  Dean Camera committed Jun 06, 2010 74 75 76  RingBuff_Data_t Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */ RingBuff_Data_t* In; /**< Current storage location in the circular buffer */ RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */  Dean Camera committed Aug 01, 2010 77  RingBuff_Count_t Count;  Dean Camera committed Jun 06, 2010 78  } RingBuff_t;  79   Dean Camera committed Jun 06, 2010 80  /* Inline Functions: */  Dean Camera committed Aug 01, 2010 81  /** Initializes a ring buffer ready for use. Buffers must be initialized via this function  Dean Camera committed Jun 06, 2010 82 83 84  * before any operations are called upon them. Already initialized buffers may be reset * by re-initializing them using this function. *  Dean Camera committed Jun 10, 2010 85  * \param[out] Buffer Pointer to a ring buffer structure to initialize  Dean Camera committed Jun 06, 2010 86  */  Dean Camera committed Jun 06, 2010 87 88  static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer) {  Dean Camera committed Aug 01, 2010 89 90 91 92 93  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { Buffer->In = Buffer->Buffer; Buffer->Out = Buffer->Buffer; }  Dean Camera committed Jun 06, 2010 94  }  95   Dean Camera committed Aug 01, 2010 96 97 98 99 100  /** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed * by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so that * the buffer cannot be modified while the computation takes place. This value should be cached * when reading out the contents of the buffer, so that as small a time as possible is spent * in an atomic lock.  101  *  Dean Camera committed Aug 01, 2010 102 103 104 105  * \note The value returned by this function is guaranteed to only be the minimum number of bytes * stored in the given buffer; this value may change as other threads write new data and so * the returned number should be used only to determine how many successive reads may safely * be performed on the buffer.  106  *  Dean Camera committed Aug 01, 2010 107 108 109  * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed */ static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)  110  {  Dean Camera committed Aug 01, 2010 111  RingBuff_Count_t Count;  112   113 114  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {  Dean Camera committed Aug 01, 2010 115  Count = Buffer->Count;  116  }  117   Dean Camera committed Aug 01, 2010 118  return Count;  119  }  120   Dean Camera committed Aug 01, 2010 121 122 123  /** Atomically determines if the specified ring buffer contains any free space. This should * be tested before storing data to the buffer, to ensure that no data is lost due to a * buffer overrun.  Dean Camera committed Jun 06, 2010 124  *  Dean Camera committed Jun 10, 2010 125  * \param[in,out] Buffer Pointer to a ring buffer structure to insert into  Dean Camera committed Aug 01, 2010 126 127  * * \return Boolean true if the buffer contains no free space, false otherwise  128  */  Dean Camera committed Aug 01, 2010 129  static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)  Dean Camera committed Jun 06, 2010 130  {  Dean Camera committed Aug 01, 2010 131  return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);  Dean Camera committed Jun 06, 2010 132 133  }  Dean Camera committed Aug 01, 2010 134 135 136  /** Atomically determines if the specified ring buffer contains any data. This should * be tested before removing data from the buffer, to ensure that the buffer does not * underflow.  Dean Camera committed Jun 06, 2010 137  *  Dean Camera committed Aug 01, 2010 138 139 140  * If the data is to be removed in a loop, store the total number of bytes stored in the * buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable * to reduce the time spent in atomicity locks.  Dean Camera committed Jun 06, 2010 141  *  Dean Camera committed Aug 01, 2010 142 143 144  * \param[in,out] Buffer Pointer to a ring buffer structure to insert into * * \return Boolean true if the buffer contains no free space, false otherwise  145  */  Dean Camera committed Aug 01, 2010 146  static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)  Dean Camera committed Jun 06, 2010 147  {  Dean Camera committed Aug 01, 2010 148  return (RingBuffer_GetCount(Buffer) == 0);  Dean Camera committed Jun 06, 2010 149 150  }  Dean Camera committed Jul 12, 2010 151  /** Inserts an element into the ring buffer.  Dean Camera committed Aug 01, 2010 152 153 154 155  * * \note Only one execution thread (main program thread or an ISR) may insert into a single buffer * otherwise data corruption may occur. Insertion and removal may occur from different execution * threads.  Dean Camera committed Jul 12, 2010 156 157 158 159  * * \param[in,out] Buffer Pointer to a ring buffer structure to insert into * \param[in] Data Data element to insert into the buffer */  Dean Camera committed Jul 21, 2010 160 161  static inline void RingBuffer_Insert(RingBuff_t* const Buffer, const RingBuff_Data_t Data)  Dean Camera committed Jul 12, 2010 162 163  { *Buffer->In = Data;  164   Dean Camera committed Jul 12, 2010 165 166  if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE]) Buffer->In = Buffer->Buffer;  Dean Camera committed Aug 01, 2010 167 168 169 170 171  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { Buffer->Count++; }  Dean Camera committed Jul 12, 2010 172 173  }  Dean Camera committed Aug 01, 2010 174 175 176 177 178  /** Removes an element from the ring buffer. * * \note Only one execution thread (main program thread or an ISR) may remove from a single buffer * otherwise data corruption may occur. Insertion and removal may occur from different execution * threads.  Dean Camera committed Jul 12, 2010 179 180 181 182 183 184 185 186  * * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from * * \return Next data element stored in the buffer */ static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer) { RingBuff_Data_t Data = *Buffer->Out;  187   Dean Camera committed Jul 12, 2010 188 189 190  if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE]) Buffer->Out = Buffer->Buffer;  Dean Camera committed Aug 01, 2010 191 192 193 194  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { Buffer->Count--; }  195   Dean Camera committed Jul 12, 2010 196 197 198  return Data; }  Dean Camera committed Dec 12, 2010 199 200 201 202 203 204 205 206 207 208 209  /** Returns the next element stored in the ring buffer, without removing it. * * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from * * \return Next data element stored in the buffer */ static inline RingBuff_Data_t RingBuffer_Peek(RingBuff_t* const Buffer) { return *Buffer->Out; }  Dean Camera committed Jun 06, 2010 210 #endif  211