vt100: include pgmspace.h as we use PROGMEM macro
[aversive.git] / modules / comm / uart / uart.c
1 /*  
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
3  * 
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: uart.c,v 1.33.4.7 2009-01-23 23:08:42 zer0 Exp $
19  *
20  */
21
22 /* Olivier MATZ, Droids-corp 2004 - 2009 */
23
24 #include <aversive.h>
25 #include <aversive/list.h>
26
27 #include <uart.h>
28 #include <uart_defs.h>
29 #include <uart_private.h>
30
31 struct cirbuf g_tx_fifo[UART_HW_NUM];
32 struct cirbuf g_rx_fifo[UART_HW_NUM];
33
34 /* global vars are initialized to 0 (NULL) */
35 event *rx_event[UART_HW_NUM];
36 event *tx_event[UART_HW_NUM];
37
38 const struct regs uart_regs[UART_HW_NUM] = {
39 #ifdef UDR0
40         {
41                 .udr = &UDR0,
42                 .ucsra = &UCSR0A,
43                 .ucsrb = &UCSR0B,
44                 .ucsrc = &UCSR0C,
45                 .ubrrl = &UBRR0L,
46                 .ubrrh = &UBRR0H,
47         },
48 #endif
49 #ifdef UDR1
50         {
51                 .udr = &UDR1,
52                 .ucsra = &UCSR1A,
53                 .ucsrb = &UCSR1B,
54                 .ucsrc = &UCSR1C,
55                 .ubrrl = &UBRR1L,
56                 .ubrrh = &UBRR1H,
57         },
58 #endif
59 #ifdef UDR2
60         {
61                 .udr = &UDR2,
62                 .ucsra = &UCSR2A,
63                 .ucsrb = &UCSR2B,
64                 .ucsrc = &UCSR2C,
65                 .ubrrl = &UBRR2L,
66                 .ubrrh = &UBRR2H,
67         },
68 #endif
69 #ifdef UDR3
70         {
71                 .udr = &UDR3,
72                 .ucsra = &UCSR3A,
73                 .ucsrb = &UCSR3B,
74                 .ucsrc = &UCSR3C,
75                 .ubrrl = &UBRR3L,
76                 .ubrrh = &UBRR3H,
77         },
78 #endif
79 };
80
81 /**
82  * This is the interruption function which occurs when the entire
83  * frame in the transmit shift register has been shifted out and 
84  * there is no new data in the transmit buffer.
85  */
86 #ifdef UART0_COMPILE
87 #ifndef USART0_UDRE_vect
88 #if defined(USART_UDRE_vect)
89 #define USART0_UDRE_vect USART_UDRE_vect
90 #elif defined(SIG_USART0_DATA)
91 #define USART0_UDRE_vect SIG_USART0_DATA
92 #elif defined(SIG_UART0_DATA)
93 #define USART0_UDRE_vect SIG_UART0_DATA
94 #endif
95 #endif
96 SIGNAL(USART0_UDRE_vect)
97 {
98         uart_send_next_char(0);
99 }
100 #endif
101 #ifdef UART1_COMPILE
102 #ifndef USART1_UDRE_vect
103 #if defined(SIG_USART1_DATA)
104 #define USART1_UDRE_vect SIG_USART1_DATA
105 #elif defined(SIG_UART1_DATA)
106 #define USART1_UDRE_vect SIG_UART1_DATA
107 #endif
108 #endif
109 SIGNAL(USART1_UDRE_vect)
110 {
111         uart_send_next_char(1);
112 }
113 #endif
114 #ifdef UART2_COMPILE
115 #ifndef USART2_UDRE_vect
116 #if defined(SIG_USART2_DATA)
117 #define USART2_UDRE_vect SIG_USART2_DATA
118 #elif defined(SIG_UART2_DATA)
119 #define USART2_UDRE_vect SIG_UART2_DATA
120 #endif
121 #endif
122 SIGNAL(USART2_UDRE_vect)
123 {
124         uart_send_next_char(2);
125 }
126 #endif
127 #ifdef UART3_COMPILE
128 #ifndef USART3_UDRE_vect
129 #if defined(SIG_USART3_DATA)
130 #define USART3_UDRE_vect SIG_USART3_DATA
131 #elif defined(SIG_UART3_DATA)
132 #define USART3_UDRE_vect SIG_UART3_DATA
133 #endif
134 #endif
135 SIGNAL(USART3_UDRE_vect)
136 {
137         uart_send_next_char(3);
138 }
139 #endif
140
141 static void uart_recv_next_char(uint8_t num);
142
143 /**
144  * This is the interruption function which occurs when there is
145  * a new unread data in the reception buffer.
146  */
147 #ifdef UART0_COMPILE
148 #ifndef USART0_RXC_vect
149 #if defined(USART_RXC_vect)
150 #define USART0_RXC_vect USART_RXC_vect
151 #elif defined(USART_RX_vect)
152 #define USART0_RXC_vect USART_RX_vect
153 #elif defined(USART0_RX_vect)
154 #define USART0_RXC_vect USART0_RX_vect
155 #else
156 #if defined(SIG_USART0_RECV)
157 #define USART0_RXC_vect SIG_USART0_RECV
158 #elif defined(SIG_UART0_RECV)
159 #define USART0_RXC_vect SIG_UART0_RECV
160 #endif
161 #endif
162 #endif
163 SIGNAL(USART0_RXC_vect)
164 {
165         uart_recv_next_char(0);
166 }
167 #endif
168 #ifdef UART1_COMPILE
169 #ifndef USART1_RXC_vect
170 #if defined(USART1_RX_vect)
171 #define USART1_RXC_vect USART1_RX_vect
172 #else
173 #if defined(SIG_USART1_RECV)
174 #define USART1_RXC_vect SIG_USART1_RECV
175 #elif defined(SIG_UART1_RECV)
176 #define USART1_RXC_vect SIG_UART1_RECV
177 #endif
178 #endif
179 #endif
180 SIGNAL(USART1_RXC_vect)
181 {
182         uart_recv_next_char(1);
183 }
184 #endif
185 #ifdef UART2_COMPILE
186 #ifndef USART2_RXC_vect
187 #if defined(USART2_RX_vect)
188 #define USART2_RXC_vect USART2_RX_vect
189 #else
190 #if defined(SIG_USART2_RECV)
191 #define USART2_RXC_vect SIG_USART2_RECV
192 #elif defined(SIG_UART2_RECV)
193 #define USART2_RXC_vect SIG_UART2_RECV
194 #endif
195 #endif
196 #endif
197 SIGNAL(USART2_RXC_vect)
198 {
199         uart_recv_next_char(2);
200 }
201 #endif
202 #ifdef UART3_COMPILE
203 #ifndef USART3_RXC_vect
204 #if defined(USART3_RX_vect)
205 #define USART3_RXC_vect USART3_RX_vect
206 #else
207 #if defined(SIG_USART3_RECV)
208 #define USART3_RX_vect SIG_USART3_RECV
209 #elif defined(SIG_UART3_RECV)
210 #define USART3_RX_vect SIG_UART3_RECV
211 #endif
212 #endif
213 #endif
214 SIGNAL(USART3_RXC_vect)
215 {
216         uart_recv_next_char(3);
217 }
218 #endif
219
220
221 /** 
222  * transmit next character of fifo if any, and call the event function.
223  * This function is executed with intr locked.
224  */
225 void uart_send_next_char(uint8_t num)
226 {
227 #ifdef CONFIG_MODULE_UART_9BITS
228         if (uart_getconf_nbits(num) == 9) {
229                 int elt = 0;
230
231                 /* for 9 bits, it uses 2 places in the fifo */
232                 if (CIRBUF_GET_LEN(&g_tx_fifo[num]) < 2) {
233                         cbi(*uart_regs[num].ucsrb, UDRIE);
234                         return;
235                 }
236
237                 cirbuf_get_buf_tail(&g_tx_fifo[num], (char *)&elt, 2);
238                 cirbuf_del_buf_tail(&g_tx_fifo[num], 2);
239
240                 uart_set_udr_9bits(num, elt);
241                 sbi(*uart_regs[num].ucsrb, UDRIE);
242         }
243         else /* 5, 6, 7 or 8 bits */
244 #endif /* CONFIG_MODULE_UART_9BITS */
245         { 
246                 char elt = 0;
247
248                 if (CIRBUF_IS_EMPTY(&g_tx_fifo[num])) {
249                         cbi(*uart_regs[num].ucsrb, UDRIE);
250                         return;
251                 }
252
253                 elt = cirbuf_get_tail(&g_tx_fifo[num]);
254                 cirbuf_del_tail(&g_tx_fifo[num]);
255                 uart_set_udr(num, elt);
256                 sbi(*uart_regs[num].ucsrb, UDRIE);
257         }
258 }
259
260 /**
261  * UART RX Interrupt
262  */
263 static void uart_recv_next_char(uint8_t num)
264 {
265 #ifdef CONFIG_MODULE_UART_9BITS
266         if (uart_getconf_nbits() == 9) {
267                 int elt = 0;
268
269                 elt = uart_get_udr_9bits(num);
270                 if (CIRBUF_GET_FREELEN(&g_rx_fifo[num]) >= 2) {
271                         cirbuf_add_buf_head(&g_rx_fifo[num], (char *)&elt, 2);
272                 }
273
274                 if (rx_event[num])
275                         ((event_9bits *)rx_event[num])(elt);
276         }
277         else 
278 #endif /* CONFIG_MODULE_UART_9BITS */
279         {
280                 char elt = 0;
281
282                 elt = uart_get_udr(num);
283                 if (!CIRBUF_IS_FULL(&g_rx_fifo[num])) {
284                         cirbuf_add_head(&g_rx_fifo[num], elt);
285                 }
286
287                 if (rx_event[num])
288                         rx_event[num](elt);
289         }
290 }
291
292 /* init all uarts */
293 void uart_init(void)
294 {
295 #if (defined UDR0) && (defined UART0_COMPILE)
296         uart_setconf(0, NULL);
297 #endif
298
299 #if (defined UDR1) && (defined UART1_COMPILE)
300         uart_setconf(1, NULL);
301 #endif
302
303 #if (defined UDR2) && (defined UART2_COMPILE)
304         uart_setconf(2, NULL);
305 #endif
306
307 #if (defined UDR3) && (defined UART3_COMPILE)
308         uart_setconf(3, NULL);
309 #endif
310 }