Add dual-license information.
[bertos.git] / mware / fifobuf.h
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003,2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 2001 Bernardo Innocenti <bernie@develer.com>
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief General pourpose FIFO buffer implemented with a ring buffer
14  *
15  * \li \c begin punta al primo elemento del buffer,
16  * \li \c end punta all'ultimo elemento,
17  * \li \c head punta al prossimo elemento che verra' estratto,
18  * \li \c tail punta alla posizione successiva all'ultimo elemento inserito.
19  * \li quando uno dei due puntatori raggiunge @c end, viene resettato a @c begin.
20  *
21  * <pre>
22  *
23  *  +-----------------------------------+
24  *  |  vuoto  |   dati validi  |  vuoto |
25  *  +-----------------------------------+
26  *  ^         ^                ^        ^
27  *  begin    head             tail     end
28  *
29  * </pre>
30  *
31  * Il buffer e' VUOTO quando head e tail coincidono:
32  *              \code head == tail \endcode
33  *
34  * Il buffer e' PIENO quando tail si trova immediatamente dietro a head:
35  *              \code tail == head - 1 \endcode
36  *
37  * Il buffer e' PIENO anche quando tail e' posizionato
38  * sull'ultima posizione del buffer e head sulla prima:
39  *              \code head == begin && tail == end \endcode
40  */
41
42 /*
43  * $Log$
44  * Revision 1.2  2004/06/03 11:27:09  bernie
45  * Add dual-license information.
46  *
47  * Revision 1.1  2004/05/23 15:43:16  bernie
48  * Import mware modules.
49  *
50  * Revision 1.3  2004/05/22 17:55:58  rasky
51  * \samp non esiste in doxygen
52  *
53  * Revision 1.2  2004/04/27 11:13:29  rasky
54  * Spostate tutte le definizioni CPU-specific da compiler.h nel nuovo file cpu.h
55  *
56  * Revision 1.1  2004/04/21 17:38:25  rasky
57  * New application
58  *
59  * Revision 1.4  2004/03/24 15:37:03  bernie
60  * Remove Copyright messages from Doxygen output
61  *
62  * Revision 1.3  2004/03/18 18:11:07  bernie
63  * Add thread-safe FIFO handling macros
64  *
65  * Revision 1.2  2004/03/01 08:00:36  bernie
66  * Fixes for Doxygen
67  *
68  * Revision 1.1  2003/12/07 04:04:20  bernie
69  * Initial project_ks framework.
70  *
71  * Revision 1.1  2003/11/21 16:36:17  aleph
72  * Rename from fifo to fifobuf to avoid conflict with BSP fifo.h header
73  *
74  * Revision 1.1  2003/11/20 22:17:41  aleph
75  * Add fifo buffer used by serial
76  *
77  */
78
79 #ifndef MWARE_FIFO_H
80 #define MWARE_FIFO_H
81
82 #include "cpu.h"
83 #ifndef COMPILER_H
84 #include "compiler.h"
85 #endif
86
87 typedef struct FIFOBuffer
88 {
89         unsigned char *head;
90         unsigned char *tail;
91         unsigned char *begin;
92         unsigned char *end;
93 } FIFOBuffer;
94
95 /* Public function prototypes */
96 void fifo_init(volatile FIFOBuffer *fb, unsigned char *buf, size_t size);
97
98 #pragma interrupt called
99 void fifo_push(volatile FIFOBuffer *fb, unsigned char c);
100
101 #pragma interrupt called
102 unsigned char fifo_pop(volatile FIFOBuffer *fb);
103
104
105 /*!
106  * Check whether the fifo is empty
107  *
108  * \note Calling fifo_isempty() is safe while a concurrent
109  *       execution context is calling fifo_push() or fifo_pop()
110  *       only if the CPU can atomically update a pointer.
111  */
112 #define fifo_isempty(fb)        ((fb)->head == (fb)->tail)
113
114 /*!
115  * Check whether the fifo is full
116  *
117  * \note Calling fifo_isfull() is safe while a concurrent
118  *       execution context is calling fifo_pop() and the
119  *       CPU can update a pointer atomically.
120  *       It is NOT safe when the other context calls
121  *       fifo_push().
122  *       This limitation is not usually problematic in a
123  *       consumer/producer scenario because the
124  *       fifo_isfull() and fifo_push() are usually called
125  *       in the producer context.
126  */
127 #define fifo_isfull(fb) \
128         ((((fb)->head == (fb)->begin) && ((fb)->tail == (fb)->end)) \
129         || ((fb)->tail == (fb)->head - 1))
130
131 /*!
132  * Make the fifo empty, discarding all its current contents.
133  */
134 #define fifo_flush(fb)  ((fb)->head = (fb)->tail)
135
136 #if !defined(__AVR__)
137
138         /* No tricks needed on 16/32bit CPUs */
139 #       define fifo_isempty_locked(fb) fifo_isempty((fb))
140
141 #else /* !__AVR__ */
142
143         INLINE bool fifo_isempty_locked(const volatile FIFOBuffer *_fb);
144         INLINE bool fifo_isempty_locked(const volatile FIFOBuffer *_fb)
145         {
146                 bool _result;
147                 cpuflags_t _flags;
148
149                 DISABLE_IRQSAVE(_flags);
150                 _result = fifo_isempty(_fb);
151                 ENABLE_IRQRESTORE(_flags);
152
153                 return _result;
154         }
155
156 #endif /* !__AVR__ */
157
158 /*!
159  * Thread safe version of fifo_isfull()
160  */
161 INLINE bool fifo_isfull_locked(const volatile FIFOBuffer *_fb);
162 INLINE bool fifo_isfull_locked(const volatile FIFOBuffer *_fb)
163 {
164         bool _result;
165         cpuflags_t _flags;
166
167         DISABLE_IRQSAVE(_flags);
168         _result = fifo_isfull(_fb);
169         ENABLE_IRQRESTORE(_flags);
170
171         return _result;
172 }
173
174 #endif /* MWARE_FIFOBUF_H */
175