cmdline: replace printf printf_P
[protos/xbee-avr.git] / 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 SIG_UART0_DATA
88 #define SIG_UART0_DATA USART0_UDRE_vect
89 #endif
90 #ifndef SIG_UART0_DATA
91 #define SIG_UART0_DATA SIG_USART0_DATA
92 #endif
93 SIGNAL(SIG_UART0_DATA)
94 {
95         uart_send_next_char(0);
96 }
97 #endif
98 #ifdef UART1_COMPILE
99 #ifndef SIG_UART1_DATA
100 #define SIG_UART1_DATA USART1_UDRE_vect
101 #endif
102 #ifndef SIG_UART1_DATA
103 #define SIG_UART1_DATA SIG_USART1_DATA
104 #endif
105 SIGNAL(SIG_UART1_DATA)
106 {
107         uart_send_next_char(1);
108 }
109 #endif
110 #ifdef UART2_COMPILE
111 #ifndef SIG_UART2_DATA
112 #define SIG_UART2_DATA USART2_UDRE_vect
113 #endif
114 #ifndef SIG_UART2_DATA
115 #define SIG_UART2_DATA SIG_USART2_DATA
116 #endif
117 SIGNAL(SIG_UART2_DATA)
118 {
119         uart_send_next_char(2);
120 }
121 #endif
122 #ifdef UART3_COMPILE
123 #ifndef SIG_UART3_DATA
124 #define SIG_UART3_DATA USART3_UDRE_vect
125 #endif
126 #ifndef SIG_UART3_DATA
127 #define SIG_UART3_DATA SIG_USART3_DATA
128 #endif
129 SIGNAL(SIG_UART3_DATA)
130 {
131         uart_send_next_char(3);
132 }
133 #endif
134
135 static void uart_recv_next_char(uint8_t num);
136
137 /**
138  * This is the interruption function which occurs when there is
139  * a new unread data in the reception buffer.
140  */
141 #ifdef UART0_COMPILE
142 #ifndef SIG_UART0_RECV
143 #define SIG_UART0_RECV USART0_RX_vect
144 #endif
145 #ifndef SIG_UART0_RECV
146 #define SIG_UART0_RECV SIG_USART0_RECV
147 #endif
148 SIGNAL(SIG_UART0_RECV)
149 {
150         uart_recv_next_char(0);
151 }
152 #endif
153 #ifdef UART1_COMPILE
154 #ifndef SIG_UART1_RECV
155 #define SIG_UART1_RECV USART1_RX_vect
156 #endif
157 #ifndef SIG_UART1_RECV
158 #define SIG_UART1_RECV SIG_USART1_RECV
159 #endif
160 SIGNAL(SIG_UART1_RECV)
161 {
162         uart_recv_next_char(1);
163 }
164 #endif
165 #ifdef UART2_COMPILE
166 #ifndef SIG_UART2_RECV
167 #define SIG_UART2_RECV USART2_RX_vect
168 #endif
169 #ifndef SIG_UART2_RECV
170 #define SIG_UART2_RECV SIG_USART2_RECV
171 #endif
172 SIGNAL(SIG_UART2_RECV)
173 {
174         uart_recv_next_char(2);
175 }
176 #endif
177 #ifdef UART3_COMPILE
178 #ifndef SIG_UART3_RECV
179 #define SIG_UART3_RECV USART3_RX_vect
180 #endif
181 #ifndef SIG_UART3_RECV
182 #define SIG_UART3_RECV SIG_USART3_RECV
183 #endif
184 SIGNAL(SIG_UART3_RECV)
185 {
186         uart_recv_next_char(3);
187 }
188 #endif
189
190
191 /** 
192  * transmit next character of fifo if any, and call the event function.
193  * This function is executed with intr locked.
194  */
195 void uart_send_next_char(uint8_t num)
196 {
197 #ifdef CONFIG_MODULE_UART_9BITS
198         if (uart_getconf_nbits(num) == 9) {
199                 int elt = 0;
200
201                 /* for 9 bits, it uses 2 places in the fifo */
202                 if (CIRBUF_GET_LEN(&g_tx_fifo[num]) < 2) {
203                         cbi(*uart_regs[num].ucsrb, UDRIE);
204                         return;
205                 }
206
207                 cirbuf_get_buf_tail(&g_tx_fifo[num], (char *)&elt, 2);
208                 cirbuf_del_buf_tail(&g_tx_fifo[num], 2);
209
210                 uart_set_udr_9bits(num, elt);
211                 sbi(*uart_regs[num].ucsrb, UDRIE);
212         }
213         else /* 5, 6, 7 or 8 bits */
214 #endif /* CONFIG_MODULE_UART_9BITS */
215         { 
216                 char elt = 0;
217
218                 if (CIRBUF_IS_EMPTY(&g_tx_fifo[num])) {
219                         cbi(*uart_regs[num].ucsrb, UDRIE);
220                         return;
221                 }
222
223                 elt = cirbuf_get_tail(&g_tx_fifo[num]);
224                 cirbuf_del_tail(&g_tx_fifo[num]);
225                 uart_set_udr(num, elt);
226                 sbi(*uart_regs[num].ucsrb, UDRIE);
227         }
228 }
229
230 /**
231  * UART RX Interrupt
232  */
233 static void uart_recv_next_char(uint8_t num)
234 {
235 #ifdef CONFIG_MODULE_UART_9BITS
236         if (uart_getconf_nbits() == 9) {
237                 int elt = 0;
238
239                 elt = uart_get_udr_9bits(num);
240                 if (CIRBUF_GET_FREELEN(&g_rx_fifo[num]) >= 2) {
241                         cirbuf_add_buf_head(&g_rx_fifo[num], (char *)&elt, 2);
242                 }
243
244                 if (rx_event[num])
245                         ((event_9bits *)rx_event[num])(elt);
246         }
247         else 
248 #endif /* CONFIG_MODULE_UART_9BITS */
249         {
250                 char elt = 0;
251
252                 elt = uart_get_udr(num);
253                 if (!CIRBUF_IS_FULL(&g_rx_fifo[num])) {
254                         cirbuf_add_head(&g_rx_fifo[num], elt);
255                 }
256
257                 if (rx_event[num])
258                         rx_event[num](elt);
259         }
260 }
261
262 /* init all uarts */
263 void uart_init(void)
264 {
265 #if (defined UDR0) && (defined UART0_COMPILE)
266         uart_setconf(0, NULL);
267 #endif
268
269 #if (defined UDR1) && (defined UART1_COMPILE)
270         uart_setconf(1, NULL);
271 #endif
272
273 #if (defined UDR2) && (defined UART2_COMPILE)
274         uart_setconf(2, NULL);
275 #endif
276
277 #if (defined UDR3) && (defined UART3_COMPILE)
278         uart_setconf(3, NULL);
279 #endif
280 }