fifobuf.h
Go to the documentation of this file.00001
00067 #ifndef STRUCT_FIFO_H
00068 #define STRUCT_FIFO_H
00069
00070 #include <cpu/types.h>
00071 #include <cpu/irq.h>
00072 #include <cfg/debug.h>
00073
00074 typedef struct FIFOBuffer
00075 {
00076 unsigned char * volatile head;
00077 unsigned char * volatile tail;
00078 unsigned char *begin;
00079 unsigned char *end;
00080 } FIFOBuffer;
00081
00082
00083 #define ASSERT_VALID_FIFO(fifo) \
00084 ATOMIC( \
00085 ASSERT((fifo)->head >= (fifo)->begin); \
00086 ASSERT((fifo)->head <= (fifo)->end); \
00087 ASSERT((fifo)->tail >= (fifo)->begin); \
00088 ASSERT((fifo)->tail <= (fifo)->end); \
00089 )
00090
00091
00102 INLINE bool fifo_isempty(const FIFOBuffer *fb)
00103 {
00104
00105 return fb->head == fb->tail;
00106 }
00107
00108
00122 INLINE bool fifo_isfull(const FIFOBuffer *fb)
00123 {
00124
00125 return
00126 ((fb->head == fb->begin) && (fb->tail == fb->end))
00127 || (fb->tail == fb->head - 1);
00128 }
00129
00130
00145 INLINE void fifo_push(FIFOBuffer *fb, unsigned char c)
00146 {
00147 #ifdef __MWERKS__
00148 #pragma interrupt called
00149 #endif
00150
00151
00152
00153 *(fb->tail) = c;
00154
00155 if (UNLIKELY(fb->tail == fb->end))
00156
00157 fb->tail = fb->begin;
00158 else
00159
00160 fb->tail++;
00161 }
00162
00163
00174 INLINE unsigned char fifo_pop(FIFOBuffer *fb)
00175 {
00176 #ifdef __MWERKS__
00177 #pragma interrupt called
00178 #endif
00179
00180
00181 if (UNLIKELY(fb->head == fb->end))
00182 {
00183
00184 fb->head = fb->begin;
00185 return *(fb->end);
00186 }
00187 else
00188
00189 return *(fb->head++);
00190 }
00191
00192
00196 INLINE void fifo_flush(FIFOBuffer *fb)
00197 {
00198
00199 fb->head = fb->tail;
00200 }
00201
00202
00203 #if CPU_REG_BITS >= CPU_BITS_PER_PTR
00204
00205
00206
00207
00208
00209 #define fifo_isempty_locked(fb) fifo_isempty((fb))
00210 #define fifo_push_locked(fb, c) fifo_push((fb), (c))
00211 #define fifo_pop_locked(fb) fifo_pop((fb))
00212 #define fifo_flush_locked(fb) fifo_flush((fb))
00213
00214 #else
00215
00224 INLINE bool fifo_isempty_locked(const FIFOBuffer *fb)
00225 {
00226 bool result;
00227 ATOMIC(result = fifo_isempty(fb));
00228 return result;
00229 }
00230
00231
00240 INLINE void fifo_push_locked(FIFOBuffer *fb, unsigned char c)
00241 {
00242 ATOMIC(fifo_push(fb, c));
00243 }
00244
00245
00246 INLINE unsigned char fifo_pop_locked(FIFOBuffer *fb)
00247 {
00248 unsigned char c;
00249 ATOMIC(c = fifo_pop(fb));
00250 return c;
00251 }
00252
00261 INLINE void fifo_flush_locked(FIFOBuffer *fb)
00262 {
00263 ATOMIC(fifo_flush(fb));
00264 }
00265
00266 #endif
00267
00268
00272 INLINE bool fifo_isfull_locked(const FIFOBuffer *_fb)
00273 {
00274 bool result;
00275 ATOMIC(result = fifo_isfull(_fb));
00276 return result;
00277 }
00278
00279
00283 INLINE void fifo_init(FIFOBuffer *fb, unsigned char *buf, size_t size)
00284 {
00285
00286 ASSERT(size > 1);
00287
00288 fb->head = fb->tail = fb->begin = buf;
00289 fb->end = buf + size - 1;
00290 }
00291
00295 INLINE size_t fifo_len(FIFOBuffer *fb)
00296 {
00297 return fb->end - fb->begin;
00298 }
00299
00300
00301 #if 0
00302
00303
00304
00305
00306 void fifo_pushblock(FIFOBuffer *fb, unsigned char *block, size_t len)
00307 {
00308 size_t freelen;
00309
00310
00311 if (fb->tail >= fb->head)
00312 {
00313 freelen = fb->end - fb->tail + 1;
00314
00315
00316 if (freelen < len)
00317 {
00318
00319 memcpy(fb->tail, block, freelen);
00320 block += freelen;
00321 len -= freelen;
00322 fb->tail = fb->begin;
00323 }
00324 else
00325 {
00326
00327 memcpy(fb->tail, block, len);
00328 fb->tail += len;
00329 return;
00330 }
00331 }
00332
00333 for(;;)
00334 {
00335 while (!(freelen = fb->head - fb->tail - 1))
00336 Delay(FIFO_POLLDELAY);
00337
00338
00339 if (freelen < len)
00340 {
00341
00342 memcpy(fb->tail, block, freelen);
00343 block += freelen;
00344 len -= freelen;
00345 fb->tail += freelen;
00346 }
00347 else
00348 {
00349
00350 memcpy(fb->tail, block, len);
00351 fb->tail += len;
00352 return;
00353 }
00354 }
00355 }
00356 #endif
00357
00358 #endif