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