new command to change the baudrate of the xbee
[protos/xbee-avr.git] / uart_setconf.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_setconf.c,v 1.1.2.3 2009-01-03 16:24:50 zer0 Exp $
19  *
20  */
21
22 /* Olivier MATZ, Droids-corp 2004 - 2009 */
23
24 #include <uart.h>
25 #include <uart_defs.h>
26 #include <uart_private.h>
27
28 /** The emission fifo of uart  */
29 #ifdef UART0_COMPILE
30 char g_tx0_buf[UART0_TX_FIFO_SIZE];
31 char g_rx0_buf[UART0_RX_FIFO_SIZE];
32 #endif
33 #ifdef UART1_COMPILE
34 char g_tx1_buf[UART1_TX_FIFO_SIZE];
35 char g_rx1_buf[UART1_RX_FIFO_SIZE];
36 #endif
37 #ifdef UART2_COMPILE
38 char g_tx2_buf[UART2_TX_FIFO_SIZE];
39 char g_rx2_buf[UART2_RX_FIFO_SIZE];
40 #endif
41 #ifdef UART3_COMPILE
42 char g_tx3_buf[UART3_TX_FIFO_SIZE];
43 char g_rx3_buf[UART3_RX_FIFO_SIZE];
44 #endif
45
46 #if UART_IS_USART
47
48 static int8_t uart_set_nbits_parity(uint8_t num, struct uart_config * u)
49 {
50         uint8_t ucsrc = 0;
51
52         /* number of bit in the frame */
53 #ifdef CONFIG_MODULE_UART_9BITS
54         if (u->nbits < 5 || u->nbits > 9) {
55                 return ENOTSUP;
56         }
57 #else
58         if (u->nbits < 5 || u->nbits > 8) {
59                 return ENOTSUP;
60         }
61 #endif
62
63         ucsrc |= ( ((u->nbits - 5) & 0x03) << UCSZ0 );
64 #ifdef CONFIG_MODULE_UART_9BITS
65         if (u->nbits == 9)
66                 *uart_regs[num].ucsrb |= (1 << UCSZ2);
67         else
68 #endif
69                 *uart_regs[num].ucsrb &= ~(1 << UCSZ2);
70
71         /* parity */
72         if (u->parity == UART_PARTITY_ODD)
73                 ucsrc |= ((1 << UPM0) | (1 << UPM1));
74         else if (u->parity == UART_PARTITY_EVEN)
75                 ucsrc |= (1 << UPM1);
76         else if (u->parity != UART_PARTITY_NONE) {
77                 return EINVAL;
78         }
79
80         /* nb of stop bits */
81         if (u->stop_bits == UART_STOP_BITS_2)
82                 ucsrc |= (1 << USBS);
83         else if (u->stop_bits != UART_STOP_BITS_1)
84                 return EINVAL;
85
86 #ifdef URSEL
87         /* some uC use a special bit URSEL to access to UCSRC */
88         ucsrc |= (1<<URSEL);
89 #endif
90         *uart_regs[num].ucsrc = ucsrc;
91
92         return ESUCCESS;
93 }
94
95 #else /* UART_IS_USART */
96
97 static int8_t uart_set_nbits_parity(int8_t num, struct uart_config * u)
98 {
99         /* number of bit in the frame */
100         if (u->nbits == 8)
101                 *uart_regs[num].ucsrb &= ~(1 << CHR9);
102 #ifdef CONFIG_MODULE_UART_9BITS
103         else if (u->nbits == 9)
104                 *uart_regs[num].ucsrb |= (1 << CHR9);
105 #endif
106         else
107                 return ENOTSUP;
108
109         /* parity and stop */
110         if (u->parity != UART_PARTITY_NONE ||
111             u->stop_bits != UART_STOP_BITS_1) {
112                 return ENOTSUP;
113         }
114
115         return ESUCCESS;
116 }
117 #endif  /* UART_IS_USART */
118
119
120 #if UART_IS_USART
121
122 static int8_t uart_set_baudreg(uint8_t num, uint16_t baudreg)
123 {
124         uint8_t lo, hi;
125
126         /* set msb bit of hi to 0 (useful fot uC with URSEL, and not
127          * important for the others because the baudreg will never be
128          * as big */
129         lo = (uint8_t)baudreg;
130         hi = (uint8_t)(baudreg>>8) & 0x7F;
131
132         *uart_regs[num].ubrrl = lo;
133         *uart_regs[num].ubrrh = hi;
134
135         return ESUCCESS;
136 }
137
138 #else /* UART_IS_USART */
139
140 static int8_t uart_set_baudreg(uint8_t num, uint16_t baudreg)
141 {
142         uint8_t lo, hi;
143
144         lo=(uint8_t)baudreg;
145         hi=(uint8_t)(baudreg>>8);
146
147         if (hi != 0)
148                 return EINVAL;
149         *uart_regs[num].ubrrl = lo;
150
151         return ESUCCESS;
152 }
153 #endif /* UART_IS_USART */
154
155 /* configuration from uart_config.h */
156 #define UART_SET_STATICCONF(x)                                          \
157         u->enabled = UART##x##_ENABLED;                                 \
158         u->intr_enabled = UART##x##_INTERRUPT_ENABLED;                  \
159         u->use_double_speed = UART##x##_USE_DOUBLE_SPEED;               \
160         u->parity =  UART##x##_PARITY;                                  \
161         u->stop_bits = UART##x##_STOP_BIT;                              \
162         u->nbits = UART##x##_NBITS;                                     \
163         u->baudrate = UART##x##_BAUDRATE;                               \
164         break
165
166 int8_t uart_setconf(uint8_t num, struct uart_config *u)
167 {
168         uint8_t ret = ESUCCESS;
169         uint16_t baudrate_reg;
170         struct uart_config static_conf;
171         uint8_t flags;
172
173         IRQ_LOCK(flags);
174
175         /* static configuration */
176         if (!u) {
177                 u = &static_conf;
178                 switch (num) {
179 #ifdef UART0_COMPILE
180                 case 0:
181                         UART_SET_STATICCONF(0);
182 #endif
183 #ifdef UART1_COMPILE
184                 case 1:
185                         UART_SET_STATICCONF(1);
186 #endif
187 #ifdef UART2_COMPILE
188                 case 2:
189                         UART_SET_STATICCONF(2);
190 #endif
191 #ifdef UART3_COMPILE
192                 case 3:
193                         UART_SET_STATICCONF(3);
194 #endif
195                 default:
196                         ret = EINVAL;
197                         goto out;
198                 }
199         }
200
201         /* wait xmit finished (UDRE = 1) */
202         while( !(*uart_regs[num].ucsra & (1<<UDRE)) );
203
204         switch (num) {
205 #ifdef UART0_COMPILE
206         case 0:
207                 cirbuf_init(&g_tx_fifo[0], g_tx0_buf, 0, UART0_TX_FIFO_SIZE);
208                 cirbuf_init(&g_rx_fifo[0], g_rx0_buf, 0, UART0_RX_FIFO_SIZE);
209                 break;
210 #endif
211 #ifdef UART1_COMPILE
212         case 1:
213                 cirbuf_init(&g_tx_fifo[1], g_tx1_buf, 0, UART1_TX_FIFO_SIZE);
214                 cirbuf_init(&g_rx_fifo[1], g_rx1_buf, 0, UART1_RX_FIFO_SIZE);
215                 break;
216 #endif
217 #ifdef UART2_COMPILE
218         case 2:
219                 cirbuf_init(&g_tx_fifo[2], g_tx2_buf, 0, UART2_TX_FIFO_SIZE);
220                 cirbuf_init(&g_rx_fifo[2], g_rx2_buf, 0, UART2_RX_FIFO_SIZE);
221                 break;
222 #endif
223 #ifdef UART3_COMPILE
224         case 3:
225                 cirbuf_init(&g_tx_fifo[3], g_tx3_buf, 0, UART3_TX_FIFO_SIZE);
226                 cirbuf_init(&g_rx_fifo[3], g_rx3_buf, 0, UART3_RX_FIFO_SIZE);
227                 break;
228 #endif
229         default:
230                 ret = EINVAL;
231                 goto out;
232         }
233         *uart_regs[num].ucsra = 0;
234         
235         if (u->enabled)
236                 *uart_regs[num].ucsrb = ((1 << TXEN) | (1 << RXEN));
237         else {
238                 *uart_regs[num].ucsrb = 0;
239                 goto out; /* no more conf */
240         }
241
242         /* we only enable recv interrupt, the xmit intrpt will be
243          * enabled in the xmit function */
244         if (u->intr_enabled)
245                 *uart_regs[num].ucsrb |= (1 << RXCIE);
246
247         if (UART_HAS_U2X) { /* if u2x is supported */
248                 if (u->use_double_speed) /* u2x is enabled */
249                         *uart_regs[num].ucsra |= (1 << U2X);
250                 else
251                         *uart_regs[num].ucsra &= ~(1 << U2X);
252         }
253         else if (u->use_double_speed) {
254                 ret = ENOTSUP;
255                 goto out;
256         }
257
258         uart_set_nbits_parity(num, u);
259
260         /* baudrate */
261         if(u->use_double_speed)
262                 baudrate_reg = (F_CPU / (u->baudrate*8l)) - 1;
263         else
264                 baudrate_reg = (F_CPU / (u->baudrate*16l)) - 1;
265
266         uart_set_baudreg(num, baudrate_reg);
267
268         /* exit */
269  out:
270         IRQ_UNLOCK(flags);
271         return ret;
272 }