2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
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.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 const __code struct ao_serial_speed ao_serial_speeds[] = {
22 /* [AO_SERIAL_SPEED_4800] = */ {
24 /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
26 /* [AO_SERIAL_SPEED_9600] = */ {
28 /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
30 /* [AO_SERIAL_SPEED_19200] = */ {
32 /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
34 /* [AO_SERIAL_SPEED_57600] = */ {
36 /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
38 /* [AO_SERIAL_SPEED_115200] = */ {
40 /* .gcr = */ (12 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
44 #define AO_SERIAL_SPEED_MAX AO_SERIAL_SPEED_115200
46 #if HAS_SERIAL_1_ALT_1
47 #define SERIAL_1_RTS P0_3
49 #define SERIAL_1_RTS P1_5
52 #if HAS_SERIAL_0_ALT_1
53 #define SERIAL_0_RTS P0_5
55 #define SERIAL_0_RTS P1_3
60 volatile __xdata struct ao_fifo ao_serial0_rx_fifo;
61 volatile __xdata struct ao_fifo ao_serial0_tx_fifo;
64 ao_serial0_rx_isr(void) __interrupt 2
66 if (!ao_fifo_full(ao_serial0_rx_fifo))
67 ao_fifo_insert(ao_serial0_rx_fifo, U0DBUF);
68 ao_wakeup(&ao_serial0_rx_fifo);
69 #if USE_SERIAL_0_STDIN
70 ao_wakeup(&ao_stdin_ready);
72 #if HAS_SERIAL_0_HW_FLOW
73 if (ao_fifo_mostly(ao_serial0_rx_fifo))
78 static __xdata uint8_t ao_serial0_tx_started;
81 ao_serial0_tx_start(void)
83 if (!ao_fifo_empty(ao_serial0_tx_fifo) &&
84 !ao_serial0_tx_started)
86 ao_serial0_tx_started = 1;
87 ao_fifo_remove(ao_serial0_tx_fifo, U0DBUF);
92 ao_serial0_tx_isr(void) __interrupt 7
95 ao_serial0_tx_started = 0;
96 ao_serial0_tx_start();
97 ao_wakeup(&ao_serial0_tx_fifo);
101 ao_serial0_getchar(void) __critical
104 while (ao_fifo_empty(ao_serial0_rx_fifo))
105 ao_sleep(&ao_serial0_rx_fifo);
106 ao_fifo_remove(ao_serial0_rx_fifo, c);
107 #if HAS_SERIAL_0_HW_FLOW
108 if (ao_fifo_barely(ao_serial0_rx_fifo))
114 #if USE_SERIAL_0_STDIN
116 _ao_serial0_pollchar(void)
119 if (ao_fifo_empty(ao_serial0_rx_fifo))
120 return AO_READ_AGAIN;
121 ao_fifo_remove(ao_serial0_rx_fifo,c);
122 #if HAS_SERIAL_0_HW_FLOW
123 if (ao_fifo_barely(ao_serial0_rx_fifo))
131 ao_serial0_putchar(char c) __critical
133 while (ao_fifo_full(ao_serial0_tx_fifo))
134 ao_sleep(&ao_serial0_tx_fifo);
135 ao_fifo_insert(ao_serial0_tx_fifo, c);
136 ao_serial0_tx_start();
140 ao_serial0_drain(void) __critical
142 while (!ao_fifo_empty(ao_serial0_tx_fifo))
143 ao_sleep(&ao_serial0_tx_fifo);
147 ao_serial0_set_speed(uint8_t speed)
150 if (speed > AO_SERIAL_SPEED_MAX)
152 U0UCR |= UxUCR_FLUSH;
153 U0BAUD = ao_serial_speeds[speed].baud;
154 U0GCR = ao_serial_speeds[speed].gcr;
156 #endif /* HAS_SERIAL_0 */
160 volatile __xdata struct ao_fifo ao_serial1_rx_fifo;
161 volatile __xdata struct ao_fifo ao_serial1_tx_fifo;
164 ao_serial1_rx_isr(void) __interrupt 3
166 if (!ao_fifo_full(ao_serial1_rx_fifo))
167 ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF);
168 ao_wakeup(&ao_serial1_rx_fifo);
169 #if USE_SERIAL_1_STDIN
170 ao_wakeup(&ao_stdin_ready);
172 #if HAS_SERIAL_1_HW_FLOW
173 if (ao_fifo_mostly(ao_serial1_rx_fifo))
178 static __xdata uint8_t ao_serial1_tx_started;
181 ao_serial1_tx_start(void)
183 if (!ao_fifo_empty(ao_serial1_tx_fifo) &&
184 !ao_serial1_tx_started)
186 ao_serial1_tx_started = 1;
187 ao_fifo_remove(ao_serial1_tx_fifo, U1DBUF);
192 ao_serial1_tx_isr(void) __interrupt 14
195 ao_serial1_tx_started = 0;
196 ao_serial1_tx_start();
197 ao_wakeup(&ao_serial1_tx_fifo);
201 ao_serial1_getchar(void) __critical
204 while (ao_fifo_empty(ao_serial1_rx_fifo))
205 ao_sleep(&ao_serial1_rx_fifo);
206 ao_fifo_remove(ao_serial1_rx_fifo, c);
207 #if HAS_SERIAL_1_HW_FLOW
208 if (ao_fifo_barely(ao_serial1_rx_fifo))
214 #if USE_SERIAL_1_STDIN
216 _ao_serial1_pollchar(void)
219 if (ao_fifo_empty(ao_serial1_rx_fifo))
220 return AO_READ_AGAIN;
221 ao_fifo_remove(ao_serial1_rx_fifo,c);
222 #if HAS_SERIAL_1_HW_FLOW
223 if (ao_fifo_barely(ao_serial1_rx_fifo))
231 ao_serial1_putchar(char c) __critical
233 while (ao_fifo_full(ao_serial1_tx_fifo))
234 ao_sleep(&ao_serial1_tx_fifo);
235 ao_fifo_insert(ao_serial1_tx_fifo, c);
236 ao_serial1_tx_start();
240 ao_serial1_drain(void) __critical
242 while (!ao_fifo_empty(ao_serial1_tx_fifo))
243 ao_sleep(&ao_serial1_tx_fifo);
247 ao_serial1_set_speed(uint8_t speed)
250 if (speed > AO_SERIAL_SPEED_MAX)
252 U1UCR |= UxUCR_FLUSH;
253 U1BAUD = ao_serial_speeds[speed].baud;
254 U1GCR = ao_serial_speeds[speed].gcr;
257 #endif /* HAS_SERIAL_1 */
263 #if HAS_SERIAL_0_ALT_1
264 /* Set up the USART pin assignment */
265 PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1;
267 P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1;
269 /* Make the USART pins be controlled by the USART */
270 P0SEL |= (1 << 2) | (1 << 3);
271 #if HAS_SERIAL_0_HW_FLOW
279 /* Set up the USART pin assignment */
280 PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
282 P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) |
283 (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0);
285 /* Make the USART pins be controlled by the USART */
286 P1SEL |= (1 << 5) | (1 << 4);
287 #if HAS_SERIAL_0_HW_FLOW
296 /* UART mode with receiver enabled */
297 U0CSR = (UxCSR_MODE_UART | UxCSR_RE);
299 /* Pick a 9600 baud rate */
300 ao_serial0_set_speed(AO_SERIAL_SPEED_9600);
302 /* Reasonable serial parameters */
303 U0UCR = (UxUCR_FLUSH |
304 #if HAS_SERIAL_0_HW_FLOW
309 UxUCR_D9_EVEN_PARITY |
311 UxUCR_PARITY_DISABLE |
312 UxUCR_SPB_1_STOP_BIT |
318 #if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN
319 ao_add_stdio(_ao_serial0_pollchar,
323 #endif /* HAS_SERIAL_0 */
326 #if HAS_SERIAL_1_ALT_1
327 /* Set up the USART pin assignment */
328 PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1;
330 P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0;
332 /* Make the USART pins be controlled by the USART */
333 P0SEL |= (1 << 5) | (1 << 4);
334 #if HAS_SERIAL_1_HW_FLOW
335 /* SW RTS control (hw doesn't work) */
339 /* HW CTS. Maybe this works? */
344 /* Set up the USART pin assignment */
345 PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
347 P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) |
348 (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1);
350 /* Make the USART pins be controlled by the USART */
351 P1SEL |= (1 << 6) | (1 << 7);
352 #if HAS_SERIAL_1_HW_FLOW
353 /* SW RTS control (hw doesn't work) */
357 /* HW CTS. Maybe this works? */
363 /* UART mode with receiver enabled */
364 U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
366 /* Pick a 4800 baud rate */
367 ao_serial1_set_speed(AO_SERIAL_SPEED_4800);
369 /* Reasonable serial parameters */
370 U1UCR = (UxUCR_FLUSH |
371 #if HAS_SERIAL_1_HW_FLOW
376 UxUCR_D9_EVEN_PARITY |
378 UxUCR_PARITY_DISABLE |
379 UxUCR_SPB_1_STOP_BIT |
386 #if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN
387 ao_add_stdio(_ao_serial1_pollchar,
391 #endif /* HAS_SERIAL_1 */