Mercurial > ~darius > hgwebdir.cgi > avr-lib
annotate cons.c @ 8:119688bb743f
Don't spin forever waiting for the TWI hardware to do something.
I _think_ this will help the case where I find the micro is hanging but I
haven't seen an error from it yet.
author | darius@dons.net.au |
---|---|
date | Fri, 01 May 2009 15:21:31 +0930 |
parents | 095216e8453d |
children | b46f0c742316 |
rev | line source |
---|---|
0 | 1 /* |
2 * Console code for AVR board | |
3 * | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
4 * Copyright (c) 2008-2009 |
0 | 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" | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
36 #include "cons-reg.h" |
0 | 37 |
38 #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) | |
39 | |
40 /* Receive buffer storage */ | |
41 consbuf_t cmd; | |
42 | |
43 /* | |
44 * Stub to use with fdevopen | |
45 * | |
46 * We ignore f and always succeed | |
47 */ | |
48 static int _putc(char c, FILE *f) { | |
49 cons_putc(c); | |
50 return(0); | |
51 } | |
52 | |
53 /* | |
54 * Stub to use with fdevopen | |
55 * | |
56 * We ignore f and always succeed | |
57 */ | |
58 static int _getc(FILE *f) { | |
59 return(cons_getc()); | |
60 } | |
61 | |
62 void | |
63 cons_init(void) { | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
64 _SETBAUD(38400); |
0 | 65 |
66 /* Enable receiver and transmitter. Turn on rx interrupts */ | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
67 _INITREG(); |
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
68 |
0 | 69 fdevopen(_putc, NULL); /* Open stdout */ |
70 fdevopen(NULL, _getc); /* Open stdin */ | |
71 } | |
72 | |
73 int | |
74 cons_putc(char c) { | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
75 loop_until_bit_is_set(_UCSRA, _UDRE); |
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
76 _UDR = c; |
0 | 77 |
78 return(0); | |
79 } | |
80 | |
81 void | |
82 cons_putsP(const char *addr) { | |
83 char c; | |
84 | |
85 while ((c = pgm_read_byte_near(addr++))) | |
86 cons_putc(c); | |
87 } | |
88 | |
89 void | |
90 cons_puts(const char *addr) { | |
91 while (*addr) | |
92 cons_putc(*addr++); | |
93 } | |
94 | |
95 void | |
96 cons_puts_dec(uint8_t a, uint8_t l) { | |
97 char s[4]; | |
98 | |
99 if (l && a < 10) | |
100 cons_putsP(PSTR("0")); | |
101 cons_puts(utoa(a, s, 10)); | |
102 } | |
103 | |
104 void | |
105 cons_puts_hex(uint8_t a) { | |
106 char s[3]; | |
107 | |
108 if (a < 0x10) | |
109 cons_putc('0'); | |
110 | |
111 cons_puts(utoa(a, s, 16)); | |
112 } | |
113 | |
114 char | |
115 cons_getc(void) { | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
116 while (!(_UCSRA & _BV(_RXC))) |
0 | 117 ; |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
118 return (_UDR); |
0 | 119 } |
120 | |
121 /* Rx complete */ | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
122 ISR(_RXVECT) { |
0 | 123 char c; |
124 | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
125 while (_UCSRA & _BV(_RXC)) { |
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
126 c = _UDR; |
0 | 127 /* 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
|
128 * just throw stuff away |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
129 */ |
15d89caaf516
Add support for single UART devices, although untested apart from a compile.
darius@Inchoate
parents:
0
diff
changeset
|
130 if (cmd.state == 255) |
0 | 131 continue; |
132 | |
133 /* End of line? */ | |
134 if (c == '\n' || c == '\r') { | |
135 cmd.buf[cmd.state] = '\0'; | |
136 printf_P(PSTR("\r\n")); | |
137 cmd.len = cmd.state; | |
138 cmd.state = 255; | |
139 continue; | |
140 } | |
141 | |
142 /* Backspace/delete */ | |
143 if (c == 0x08 || c == 0x7f) { | |
144 if (cmd.state > 0) { | |
145 cmd.state--; | |
146 printf_P(PSTR("\010\040\010")); | |
147 } | |
148 continue; | |
149 } | |
150 | |
151 /* Anything unprintable just ignore it */ | |
152 if (!isprint(c)) | |
153 continue; | |
154 | |
155 cmd.buf[cmd.state] = tolower(c); | |
156 | |
157 /* Echo back to the user */ | |
158 cons_putc(cmd.buf[cmd.state]); | |
159 | |
160 cmd.state++; | |
161 /* Over flow? */ | |
162 if (cmd.state == ((sizeof(cmd.buf) / sizeof(cmd.buf[0])) - 1)) { | |
163 printf_P(PSTR("\r\nLine too long")); | |
164 cmd.state = 0; | |
165 continue; | |
166 } | |
167 } | |
168 } | |
169 | |
170 /* Tx complete */ | |
4
095216e8453d
Hide register name abstraction in a separate file.
darius@Inchoate
parents:
3
diff
changeset
|
171 ISR(_TXVECT) { |
0 | 172 } |
173 |