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; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 const __code struct ao_serial_speed ao_serial_speeds[] = {
21 /* [AO_SERIAL_SPEED_4800] = */ {
23 /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
25 /* [AO_SERIAL_SPEED_9600] = */ {
27 /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
29 /* [AO_SERIAL_SPEED_19200] = */ {
31 /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
33 /* [AO_SERIAL_SPEED_57600] = */ {
35 /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
41 volatile __xdata struct ao_fifo ao_serial0_rx_fifo;
42 volatile __xdata struct ao_fifo ao_serial0_tx_fifo;
45 ao_serial0_rx_isr(void) __interrupt 2
47 if (!ao_fifo_full(ao_serial0_rx_fifo))
48 ao_fifo_insert(ao_serial0_rx_fifo, U0DBUF);
49 ao_wakeup(&ao_serial0_rx_fifo);
50 #if USE_SERIAL_0_STDIN
51 ao_wakeup(&ao_stdin_ready);
55 static __xdata uint8_t ao_serial0_tx_started;
58 ao_serial0_tx_start(void)
60 if (!ao_fifo_empty(ao_serial0_tx_fifo) &&
61 !ao_serial0_tx_started)
63 ao_serial0_tx_started = 1;
64 ao_fifo_remove(ao_serial0_tx_fifo, U0DBUF);
69 ao_serial0_tx_isr(void) __interrupt 7
72 ao_serial0_tx_started = 0;
73 ao_serial0_tx_start();
74 ao_wakeup(&ao_serial0_tx_fifo);
78 ao_serial0_getchar(void) __critical
81 while (ao_fifo_empty(ao_serial0_rx_fifo))
82 ao_sleep(&ao_serial0_rx_fifo);
83 ao_fifo_remove(ao_serial0_rx_fifo, c);
87 #if USE_SERIAL_0_STDIN
89 ao_serial0_pollchar(void) __critical
92 if (ao_fifo_empty(ao_serial0_rx_fifo))
94 ao_fifo_remove(ao_serial0_rx_fifo,c);
100 ao_serial0_putchar(char c) __critical
102 while (ao_fifo_full(ao_serial0_tx_fifo))
103 ao_sleep(&ao_serial0_tx_fifo);
104 ao_fifo_insert(ao_serial0_tx_fifo, c);
105 ao_serial0_tx_start();
109 ao_serial0_drain(void) __critical
111 while (!ao_fifo_empty(ao_serial0_tx_fifo))
112 ao_sleep(&ao_serial0_tx_fifo);
116 ao_serial0_set_speed(uint8_t speed)
119 if (speed > AO_SERIAL_SPEED_57600)
121 U0UCR |= UxUCR_FLUSH;
122 U0BAUD = ao_serial_speeds[speed].baud;
123 U0GCR = ao_serial_speeds[speed].gcr;
125 #endif /* HAS_SERIAL_0 */
129 volatile __xdata struct ao_fifo ao_serial1_rx_fifo;
130 volatile __xdata struct ao_fifo ao_serial1_tx_fifo;
133 ao_serial1_rx_isr(void) __interrupt 3
135 if (!ao_fifo_full(ao_serial1_rx_fifo))
136 ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF);
137 ao_wakeup(&ao_serial1_rx_fifo);
138 #if USE_SERIAL_1_STDIN
139 ao_wakeup(&ao_stdin_ready);
143 static __xdata uint8_t ao_serial1_tx_started;
146 ao_serial1_tx_start(void)
148 if (!ao_fifo_empty(ao_serial1_tx_fifo) &&
149 !ao_serial1_tx_started)
151 ao_serial1_tx_started = 1;
152 ao_fifo_remove(ao_serial1_tx_fifo, U1DBUF);
157 ao_serial1_tx_isr(void) __interrupt 14
160 ao_serial1_tx_started = 0;
161 ao_serial1_tx_start();
162 ao_wakeup(&ao_serial1_tx_fifo);
166 ao_serial1_getchar(void) __critical
169 while (ao_fifo_empty(ao_serial1_rx_fifo))
170 ao_sleep(&ao_serial1_rx_fifo);
171 ao_fifo_remove(ao_serial1_rx_fifo, c);
175 #if USE_SERIAL_1_STDIN
177 ao_serial1_pollchar(void) __critical
180 if (ao_fifo_empty(ao_serial1_rx_fifo))
181 return AO_READ_AGAIN;
182 ao_fifo_remove(ao_serial1_rx_fifo,c);
188 ao_serial1_putchar(char c) __critical
190 while (ao_fifo_full(ao_serial1_tx_fifo))
191 ao_sleep(&ao_serial1_tx_fifo);
192 ao_fifo_insert(ao_serial1_tx_fifo, c);
193 ao_serial1_tx_start();
197 ao_serial1_drain(void) __critical
199 while (!ao_fifo_empty(ao_serial1_tx_fifo))
200 ao_sleep(&ao_serial1_tx_fifo);
204 ao_serial1_set_speed(uint8_t speed)
207 if (speed > AO_SERIAL_SPEED_57600)
209 U1UCR |= UxUCR_FLUSH;
210 U1BAUD = ao_serial_speeds[speed].baud;
211 U1GCR = ao_serial_speeds[speed].gcr;
214 #endif /* HAS_SERIAL_1 */
220 #if HAS_SERIAL_0_ALT_1
221 /* Set up the USART pin assignment */
222 PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1;
224 P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1;
226 /* Make the USART pins be controlled by the USART */
227 P0SEL |= (1 << 2) | (1 << 3);
228 #if HAS_SERIAL_0_HW_FLOW
229 P0SEL |= (1 << 4) | (1 << 5);
232 /* Set up the USART pin assignment */
233 PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
235 P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) |
236 (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0);
238 /* Make the USART pins be controlled by the USART */
239 P1SEL |= (1 << 5) | (1 << 4);
240 #if HAS_SERIAL_0_HW_FLOW
241 P1SEL |= (1 << 3) | (1 << 2);
245 /* UART mode with receiver enabled */
246 U0CSR = (UxCSR_MODE_UART | UxCSR_RE);
248 /* Pick a 9600 baud rate */
249 ao_serial0_set_speed(AO_SERIAL_SPEED_9600);
251 /* Reasonable serial parameters */
252 U0UCR = (UxUCR_FLUSH |
253 #if HAS_SERIAL_0_HW_FLOW
258 UxUCR_D9_EVEN_PARITY |
260 UxUCR_PARITY_DISABLE |
261 UxUCR_SPB_1_STOP_BIT |
267 #if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN
268 ao_add_stdio(ao_serial0_pollchar,
272 #endif /* HAS_SERIAL_0 */
275 #if HAS_SERIAL_1_ALT_1
276 /* Set up the USART pin assignment */
277 PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1;
279 P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0;
281 /* Make the USART pins be controlled by the USART */
282 P0SEL |= (1 << 5) | (1 << 4);
283 #if HAS_SERIAL_1_HW_FLOW
284 P0SEL |= (1 << 3) | (1 << 2);
287 /* Set up the USART pin assignment */
288 PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
290 P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) |
291 (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1);
293 /* Make the USART pins be controlled by the USART */
294 P1SEL |= (1 << 6) | (1 << 7);
295 #if HAS_SERIAL_1_HW_FLOW
296 P1SEL |= (1 << 5) | (1 << 4);
300 /* UART mode with receiver enabled */
301 U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
303 /* Pick a 4800 baud rate */
304 ao_serial1_set_speed(AO_SERIAL_SPEED_4800);
306 /* Reasonable serial parameters */
307 U1UCR = (UxUCR_FLUSH |
308 #if HAS_SERIAL_1_HW_FLOW
313 UxUCR_D9_EVEN_PARITY |
315 UxUCR_PARITY_DISABLE |
316 UxUCR_SPB_1_STOP_BIT |
323 #if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN
324 ao_add_stdio(ao_serial1_pollchar,
328 #endif /* HAS_SERIAL_1 */