fifobuf.h
Go to the documentation of this file.00001
00070 #ifndef STRUCT_FIFO_H
00071 #define STRUCT_FIFO_H
00072
00073 #include <cpu/types.h>
00074 #include <cpu/irq.h>
00075 #include <cfg/debug.h>
00076
00077 typedef struct FIFOBuffer
00078 {
00079 unsigned char * volatile head;
00080 unsigned char * volatile tail;
00081 unsigned char *begin;
00082 unsigned char *end;
00083 } FIFOBuffer;
00084
00085
00086 #define ASSERT_VALID_FIFO(fifo) \
00087 ATOMIC( \
00088 ASSERT((fifo)->head >= (fifo)->begin); \
00089 ASSERT((fifo)->head <= (fifo)->end); \
00090 ASSERT((fifo)->tail >= (fifo)->begin); \
00091 ASSERT((fifo)->tail <= (fifo)->end); \
00092 )
00093
00094
00105 INLINE bool fifo_isempty(const FIFOBuffer *fb)
00106 {
00107
00108 return fb->head == fb->tail;
00109 }
00110
00111
00125 INLINE bool fifo_isfull(const FIFOBuffer *fb)
00126 {
00127
00128 return
00129 ((fb->head == fb->begin) && (fb->tail == fb->end))
00130 || (fb->tail == fb->head - 1);
00131 }
00132
00133
00148 INLINE void fifo_push(FIFOBuffer *fb, unsigned char c)
00149 {
00150 #ifdef __MWERKS__
00151 #pragma interrupt called
00152 #endif
00153
00154
00155
00156 *(fb->tail) = c;
00157
00158 if (UNLIKELY(fb->tail == fb->end))
00159
00160 fb->tail = fb->begin;
00161 else
00162
00163 fb->tail++;
00164 }
00165
00166
00177 INLINE unsigned char fifo_pop(FIFOBuffer *fb)
00178 {
00179 #ifdef __MWERKS__
00180 #pragma interrupt called
00181 #endif
00182
00183
00184 if (UNLIKELY(fb->head == fb->end))
00185 {
00186
00187 fb->head = fb->begin;
00188 return *(fb->end);
00189 }
00190 else
00191
00192 return *(fb->head++);
00193 }
00194
00195
00199 INLINE void fifo_flush(FIFOBuffer *fb)
00200 {
00201
00202 fb->head = fb->tail;
00203 }
00204
00205
00206 #if CPU_REG_BITS >= CPU_BITS_PER_PTR
00207
00208
00209
00210
00211
00212 #define fifo_isempty_locked(fb) fifo_isempty((fb))
00213 #define fifo_push_locked(fb, c) fifo_push((fb), (c))
00214 #define fifo_pop_locked(fb) fifo_pop((fb))
00215 #define fifo_flush_locked(fb) fifo_flush((fb))
00216
00217 #else
00218
00227 INLINE bool fifo_isempty_locked(const FIFOBuffer *fb)
00228 {
00229 bool result;
00230 ATOMIC(result = fifo_isempty(fb));
00231 return result;
00232 }
00233
00234
00243 INLINE void fifo_push_locked(FIFOBuffer *fb, unsigned char c)
00244 {
00245 ATOMIC(fifo_push(fb, c));
00246 }
00247
00248
00249 INLINE unsigned char fifo_pop_locked(FIFOBuffer *fb)
00250 {
00251 unsigned char c;
00252 ATOMIC(c = fifo_pop(fb));
00253 return c;
00254 }
00255
00264 INLINE void fifo_flush_locked(FIFOBuffer *fb)
00265 {
00266 ATOMIC(fifo_flush(fb));
00267 }
00268
00269 #endif
00270
00271
00275 INLINE bool fifo_isfull_locked(const FIFOBuffer *_fb)
00276 {
00277 bool result;
00278 ATOMIC(result = fifo_isfull(_fb));
00279 return result;
00280 }
00281
00282
00286 INLINE void fifo_init(FIFOBuffer *fb, unsigned char *buf, size_t size)
00287 {
00288
00289 ASSERT(size > 1);
00290
00291 fb->head = fb->tail = fb->begin = buf;
00292 fb->end = buf + size - 1;
00293 }
00294
00298 INLINE size_t fifo_len(FIFOBuffer *fb)
00299 {
00300 return fb->end - fb->begin;
00301 }
00302
00303
00304 #if 0
00305
00306
00307
00308
00309 void fifo_pushblock(FIFOBuffer *fb, unsigned char *block, size_t len)
00310 {
00311 size_t freelen;
00312
00313
00314 if (fb->tail >= fb->head)
00315 {
00316 freelen = fb->end - fb->tail + 1;
00317
00318
00319 if (freelen < len)
00320 {
00321
00322 memcpy(fb->tail, block, freelen);
00323 block += freelen;
00324 len -= freelen;
00325 fb->tail = fb->begin;
00326 }
00327 else
00328 {
00329
00330 memcpy(fb->tail, block, len);
00331 fb->tail += len;
00332 return;
00333 }
00334 }
00335
00336 for(;;)
00337 {
00338 while (!(freelen = fb->head - fb->tail - 1))
00339 Delay(FIFO_POLLDELAY);
00340
00341
00342 if (freelen < len)
00343 {
00344
00345 memcpy(fb->tail, block, freelen);
00346 block += freelen;
00347 len -= freelen;
00348 fb->tail += freelen;
00349 }
00350 else
00351 {
00352
00353 memcpy(fb->tail, block, len);
00354 fb->tail += len;
00355 return;
00356 }
00357 }
00358 }
00359 #endif
00360
00362
00363 #endif