misc: Typos
[simavr] / simavr / sim / fifo_declare.h
1 /*
2         fifo_declare.h
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
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.
12
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.
17
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/>.
20  */
21
22 /*
23  * FIFO helpers, aka circular buffers
24  *
25  * these macros define accessory for fifos of any name and any size (power of two)
26  */
27
28 #ifndef __FIFO_DECLARE__
29 #define __FIFO_DECLARE__
30
31 /*
32         doing a :
33         DEFINE_FIFO(uint8_t, myfifo, 128);
34
35         will declare :
36         enum : myfifo_overflow_f
37         type : myfifo_t
38         functions:
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);
51
52
53         To use the fifo, you must declare at least one :
54         myfifo_t fifo = FIFO_NULL;
55
56         while (!myfifo_isfull(&fifo))
57                 myfifo_write(&fifo, 0xaa);
58         ....
59         while (!myfifo_isempty(&fifo))
60                 b = myfifo_read(&fifo);
61  */
62
63 #include <stdint.h>
64
65 #if __AVR__
66 #define FIFO_CURSOR_TYPE        uint8_t
67 #define FIFO_BOOL_TYPE  char
68 #define FIFO_INLINE
69 #endif
70 #ifndef FIFO_CURSOR_TYPE
71 #define FIFO_CURSOR_TYPE        uint16_t
72 #endif
73 #ifndef FIFO_BOOL_TYPE
74 #define FIFO_BOOL_TYPE  int
75 #endif
76 #ifndef FIFO_INLINE
77 #define FIFO_INLINE     inline
78 #endif
79
80 #define FIFO_NULL { {0}, 0, 0, 0 }
81
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;          \
89 } __name##_t
90
91 #define DEFINE_FIFO(__type, __name, __size) \
92 static FIFO_INLINE FIFO_BOOL_TYPE __name##_write(__name##_t * c, __type b)\
93 {\
94         FIFO_CURSOR_TYPE now = c->write;\
95         FIFO_CURSOR_TYPE next = (now + 1) & (__size-1);\
96         if (c->read != next) {  \
97                 c->buffer[now] = b;\
98                 c->write = next;\
99                 return 1;\
100         }\
101         return 0;\
102 }\
103 static inline FIFO_BOOL_TYPE __name##_isfull(__name##_t *c)\
104 {\
105         FIFO_CURSOR_TYPE next = (c->write + 1) & (__size-1);\
106         return c->read == next;\
107 }\
108 static inline FIFO_BOOL_TYPE __name##_isempty(__name##_t * c)\
109 {\
110         return c->read == c->write;\
111 }\
112 static FIFO_INLINE __type __name##_read(__name##_t * c)\
113 {\
114         if (c->read == c->write)\
115                 return 0;\
116         FIFO_CURSOR_TYPE read = c->read;\
117         __type res = c->buffer[read];\
118         c->read = (read + 1) & (__size-1);\
119         return res;\
120 }\
121 static inline FIFO_CURSOR_TYPE __name##_get_read_size(__name##_t *c)\
122 {\
123         return c->write > c->read ? c->write - c->read : __size - 1 - c->read + c->write;\
124 }\
125 static inline void __name##_read_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\
126 {\
127         c->read = (c->read + o) & (__size-1);\
128 }\
129 static inline __type __name##_read_at(__name##_t *c, FIFO_CURSOR_TYPE o)\
130 {\
131         return c->buffer[(c->read + o) & (__size-1)];\
132 }\
133 static inline void __name##_write_at(__name##_t *c, FIFO_CURSOR_TYPE o, __type b)\
134 {\
135         c->buffer[(c->write + o) & (__size-1)] = b;\
136 }\
137 static inline void __name##_write_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\
138 {\
139         c->write = (c->write + o) & (__size-1);\
140 }\
141 static inline void __name##_reset(__name##_t *c)\
142 {\
143         c->read = c->write = c->flags = 0;\
144 }\
145 struct __name##_t
146
147 #endif