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