Mercurial > ~darius > hgwebdir.cgi > avr-lib
annotate cons.c @ 3:15d89caaf516
Add support for single UART devices, although untested apart from a compile.
Doesn't break dual UART ones :)
Also checks for PRR before setting it.
author | darius@Inchoate |
---|---|
date | Wed, 11 Mar 2009 17:28:39 +1030 |
parents | 3879f487b661 |
children | 095216e8453d |
rev | line source |
---|---|
0 | 1 /* |
2 * Console code for AVR board | |
3 * | |
4 * Copyright (c) 2008 | |
5 * Daniel O'Connor <darius@dons.net.au>. All rights reserved. | |
6 * | |
7 * Redistribution and use in source and binary forms, with or without | |
8 * modification, are permitted provided that the following conditions | |
9 * are met: | |
10 * 1. Redistributions of source code must retain the above copyright | |
11 * notice, this list of conditions and the following disclaimer. | |
12 * 2. Redistributions in binary form must reproduce the above copyright | |
13 * notice, this list of conditions and the following disclaimer in the | |
14 * documentation and/or other materials provided with the distribution. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
19 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 * SUCH DAMAGE. | |
27 */ | |
28 | |
29 #include <ctype.h> | |
30 #include <stdio.h> | |
31 #include <stdint.h> | |
32 #include <stdlib.h> | |
33 #include <avr/interrupt.h> | |
34 #include <avr/pgmspace.h> | |
35 #include "cons.h" | |
36 | |
37 #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) | |
38 | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
39 #ifdef UBRR0 |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
40 #define DUALUART |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
41 #endif |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
42 |
0 | 43 /* Receive buffer storage */ |
44 consbuf_t cmd; | |
45 | |
46 /* | |
47 * Stub to use with fdevopen | |
48 * | |
49 * We ignore f and always succeed | |
50 */ | |
51 static int _putc(char c, FILE *f) { | |
52 cons_putc(c); | |
53 return(0); | |
54 } | |
55 | |
56 /* | |
57 * Stub to use with fdevopen | |
58 * | |
59 * We ignore f and always succeed | |
60 */ | |
61 static int _getc(FILE *f) { | |
62 return(cons_getc()); | |
63 } | |
64 | |
65 void | |
66 cons_init(void) { | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
67 #ifdef DUALUART |
0 | 68 UBRR0 = UART_BAUD_SELECT(38400, F_CPU); |
69 | |
70 /* Enable receiver and transmitter. Turn on rx interrupts */ | |
71 UCSR0A = 0; | |
72 UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0); | |
73 UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
74 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
75 UBRRH = UART_BAUD_SELECT(38400, F_CPU) >> 8; |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
76 UBRRL = (uint8_t)UART_BAUD_SELECT(38400, F_CPU); |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
77 |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
78 /* Enable receiver and transmitter. Turn on rx interrupts */ |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
79 UCSRA = 0; |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
80 UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
81 UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
82 #endif |
0 | 83 |
84 fdevopen(_putc, NULL); /* Open stdout */ | |
85 fdevopen(NULL, _getc); /* Open stdin */ | |
86 } | |
87 | |
88 int | |
89 cons_putc(char c) { | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
90 #ifdef DUALUART |
0 | 91 loop_until_bit_is_set(UCSR0A, UDRE0); |
92 UDR0 = c; | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
93 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
94 loop_until_bit_is_set(UCSRA, UDRE); |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
95 UDR = c; |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
96 #endif |
0 | 97 |
98 return(0); | |
99 } | |
100 | |
101 void | |
102 cons_putsP(const char *addr) { | |
103 char c; | |
104 | |
105 while ((c = pgm_read_byte_near(addr++))) | |
106 cons_putc(c); | |
107 } | |
108 | |
109 void | |
110 cons_puts(const char *addr) { | |
111 while (*addr) | |
112 cons_putc(*addr++); | |
113 } | |
114 | |
115 void | |
116 cons_puts_dec(uint8_t a, uint8_t l) { | |
117 char s[4]; | |
118 | |
119 if (l && a < 10) | |
120 cons_putsP(PSTR("0")); | |
121 cons_puts(utoa(a, s, 10)); | |
122 } | |
123 | |
124 void | |
125 cons_puts_hex(uint8_t a) { | |
126 char s[3]; | |
127 | |
128 if (a < 0x10) | |
129 cons_putc('0'); | |
130 | |
131 cons_puts(utoa(a, s, 16)); | |
132 } | |
133 | |
134 char | |
135 cons_getc(void) { | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
136 #ifdef DUALUART |
0 | 137 while (!(UCSR0A & _BV(RXC0))) |
138 ; | |
139 return (UDR0); | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
140 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
141 while (!(UCSRA & _BV(RXC))) |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
142 ; |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
143 return (UDR); |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
144 #endif |
0 | 145 } |
146 | |
147 /* Rx complete */ | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
148 #ifdef DUALUART |
0 | 149 ISR(USART0_RX_vect) { |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
150 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
151 ISR(USART_RXC_vect) { |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
152 #endif |
0 | 153 char c; |
154 | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
155 #ifdef DUALUART |
0 | 156 while (UCSR0A & _BV(RXC0)) { |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
157 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
158 while (UCSRA & _BV(RXC)) { |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
159 #endif |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
160 |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
161 #ifdef DUALUART |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
162 c = UDR0; |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
163 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
164 c = UDR; |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
165 #endif |
0 | 166 /* 255 means we're waiting for main to process the command, |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
167 * just throw stuff away |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
168 */ |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
169 if (cmd.state == 255) |
0 | 170 continue; |
171 | |
172 /* End of line? */ | |
173 if (c == '\n' || c == '\r') { | |
174 cmd.buf[cmd.state] = '\0'; | |
175 printf_P(PSTR("\r\n")); | |
176 cmd.len = cmd.state; | |
177 cmd.state = 255; | |
178 continue; | |
179 } | |
180 | |
181 /* Backspace/delete */ | |
182 if (c == 0x08 || c == 0x7f) { | |
183 if (cmd.state > 0) { | |
184 cmd.state--; | |
185 printf_P(PSTR("\010\040\010")); | |
186 } | |
187 continue; | |
188 } | |
189 | |
190 /* Anything unprintable just ignore it */ | |
191 if (!isprint(c)) | |
192 continue; | |
193 | |
194 cmd.buf[cmd.state] = tolower(c); | |
195 | |
196 /* Echo back to the user */ | |
197 cons_putc(cmd.buf[cmd.state]); | |
198 | |
199 cmd.state++; | |
200 /* Over flow? */ | |
201 if (cmd.state == ((sizeof(cmd.buf) / sizeof(cmd.buf[0])) - 1)) { | |
202 printf_P(PSTR("\r\nLine too long")); | |
203 cmd.state = 0; | |
204 continue; | |
205 } | |
206 } | |
207 } | |
208 | |
209 /* Tx complete */ | |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
210 #ifdef DUALUART |
0 | 211 ISR(USART0_TX_vect) { |
3
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
212 #else |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
213 ISR(USART_TXC_vect) { |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
214 #endif |
0 | 215 } |
216 |