Add dual-license information.
[bertos.git] / mware / fifobuf.c
1 /*!
2  * \file
3  * <!--
4  * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright (C) 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 FIFO buffer handling routines
14  */
15
16 /*
17  * $Log$
18  * Revision 1.2  2004/06/03 11:27:09  bernie
19  * Add dual-license information.
20  *
21  * Revision 1.1  2004/05/23 15:43:16  bernie
22  * Import mware modules.
23  *
24  */
25
26 #include "fifobuf.h"
27 #include "compiler.h"
28 #include <drv/kdebug.h>
29
30 void fifo_init(volatile FIFOBuffer *fb, unsigned char *buf, size_t size)
31 {
32         fb->head = fb->tail = fb->begin = buf;
33         fb->end = buf + size - 1;
34 }
35
36
37 /*!
38  * Pop a character from the fifo buffer.
39  *
40  * \note Calling \c fifo_push() on a full buffer is undefined.
41  *       The caller must make sure the buffer has at least
42  *       one free slot before calling this function.
43  *
44  * \note It is safe to call fifo_pop() and fifo_push() from
45  *       concurrent contexts.
46  */
47 void fifo_push(volatile FIFOBuffer *fb, unsigned char c)
48 {
49 #pragma interrupt called
50         /* Write at tail position */
51         *(fb->tail) = c;
52
53         if (fb->tail == fb->end)
54                 /* wrap tail around */
55                 fb->tail = fb->begin;
56         else
57                 /* Move tail forward */
58                 fb->tail++;
59 }
60
61 /*!
62  * Pop a character from the fifo buffer.
63  *
64  * \note Calling \c fifo_pop() on an empty buffer is undefined.
65  *       The caller must make sure the buffer contains at least
66  *       one character before calling this function.
67  *
68  * \note It is safe to call fifo_pop() and fifo_push() from
69  *       concurrent contexts.
70  */
71 unsigned char fifo_pop(volatile FIFOBuffer *fb)
72 {
73 #pragma interrupt called
74         if (fb->head == fb->end)
75         {
76                 /* wrap head around */
77                 fb->head = fb->begin;
78                 return *(fb->end);
79         }
80         else
81                 /* move head forward */
82                 return *(fb->head++);
83 }
84
85
86 #if 0
87
88 /* untested */
89 void fifo_pushblock(volatile FIFOBuffer *fb, unsigned char *block, size_t len)
90 {
91         size_t freelen;
92
93         /* Se c'e' spazio da tail alla fine del buffer */
94         if (fb->tail >= fb->head)
95         {
96                 freelen = fb->end - fb->tail + 1;
97
98                 /* C'e' abbastanza spazio per scrivere tutto il blocco? */
99                 if (freelen < len)
100                 {
101                         /* Scrivi quello che entra fino alla fine del buffer */
102                         memcpy(fb->tail, block, freelen);
103                         block += freelen;
104                         len -= freelen;
105                         fb->tail = fb->begin;
106                 }
107                 else
108                 {
109                         /* Scrivi tutto il blocco */
110                         memcpy(fb->tail, block, len);
111                         fb->tail += len;
112                         return;
113                 }
114         }
115
116         for(;;)
117         {
118                 while (!(freelen = fb->head - fb->tail - 1))
119                         Delay(FIFO_POLLDELAY);
120
121                 /* C'e' abbastanza spazio per scrivere tutto il blocco? */
122                 if (freelen < len)
123                 {
124                         /* Scrivi quello che entra fino alla fine del buffer */
125                         memcpy(fb->tail, block, freelen);
126                         block += freelen;
127                         len -= freelen;
128                         fb->tail += freelen;
129                 }
130                 else
131                 {
132                         /* Scrivi tutto il blocco */
133                         memcpy(fb->tail, block, len);
134                         fb->tail += len;
135                         return;
136                 }
137         }
138 }
139
140 #endif /* UNUSED */