4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
23 * FIFO helpers, aka circular buffers
25 * these macros define accessory for fifos of any name and any size (power of two)
28 #ifndef __FIFO_DECLARE__
29 #define __FIFO_DECLARE__
33 DEFINE_FIFO(uint8_t, myfifo, 128);
36 enum : myfifo_overflow_f
39 // write a byte into the fifo, return 1 if there was room, 0 if there wasn't
40 int myfifo_write(myfifo_t *c, uint8_t b);
41 // reads a byte from the fifo, return 0 if empty. Use myfifo_isempty() to check beforehand
42 uint8_t myfifo_read(myfifo_t *c);
43 int myfifo_isfull(myfifo_t *c);
44 int myfifo_isempty(myfifo_t *c);
45 // returns number of items to read now
46 uint16_t myfifo_get_read_size(myfifo_t *c);
47 // read item at offset o from read cursor, no cursor advance
48 uint8_t myfifo_read_at(myfifo_t *c, uint16_t o);
49 // write b at offset o compared to current write cursor, no cursor advance
50 void myfifo_write_at(myfifo_t *c, uint16_t o, uint8_t b);
53 To use the fifo, you must declare at least one :
54 myfifo_t fifo = FIFO_NULL;
56 while (!myfifo_isfull(&fifo))
57 myfifo_write(&fifo, 0xaa);
59 while (!myfifo_isempty(&fifo))
60 b = myfifo_read(&fifo);
66 #define FIFO_CURSOR_TYPE uint8_t
67 #define FIFO_BOOL_TYPE char
70 #ifndef FIFO_CURSOR_TYPE
71 #define FIFO_CURSOR_TYPE uint16_t
73 #ifndef FIFO_BOOL_TYPE
74 #define FIFO_BOOL_TYPE int
77 #define FIFO_INLINE inline
80 #define FIFO_NULL { {0}, 0, 0, 0 }
82 #define DECLARE_FIFO(__type, __name, __size) \
83 enum { __name##_overflow_f = (1 << 0) }; \
84 typedef struct __name##_t { \
85 __type buffer[__size]; \
86 volatile FIFO_CURSOR_TYPE read; \
87 volatile FIFO_CURSOR_TYPE write; \
88 volatile uint8_t flags; \
91 #define DEFINE_FIFO(__type, __name, __size) \
92 static FIFO_INLINE FIFO_BOOL_TYPE __name##_write(__name##_t * c, __type b)\
94 FIFO_CURSOR_TYPE now = c->write;\
95 FIFO_CURSOR_TYPE next = (now + 1) & (__size-1);\
96 if (c->read != next) { \
103 static inline FIFO_BOOL_TYPE __name##_isfull(__name##_t *c)\
105 FIFO_CURSOR_TYPE next = (c->write + 1) & (__size-1);\
106 return c->read == next;\
108 static inline FIFO_BOOL_TYPE __name##_isempty(__name##_t * c)\
110 return c->read == c->write;\
112 static FIFO_INLINE __type __name##_read(__name##_t * c)\
114 if (c->read == c->write)\
116 FIFO_CURSOR_TYPE read = c->read;\
117 __type res = c->buffer[read];\
118 c->read = (read + 1) & (__size-1);\
121 static inline FIFO_CURSOR_TYPE __name##_get_read_size(__name##_t *c)\
123 return c->write > c->read ? c->write - c->read : __size - 1 - c->read + c->write;\
125 static inline void __name##_read_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\
127 c->read = (c->read + o) & (__size-1);\
129 static inline __type __name##_read_at(__name##_t *c, FIFO_CURSOR_TYPE o)\
131 return c->buffer[(c->read + o) & (__size-1)];\
133 static inline void __name##_write_at(__name##_t *c, FIFO_CURSOR_TYPE o, __type b)\
135 c->buffer[(c->write + o) & (__size-1)] = b;\
137 static inline void __name##_write_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\
139 c->write = (c->write + o) & (__size-1);\
141 static inline void __name##_reset(__name##_t *c)\
143 c->read = c->write = c->flags = 0;\