Mercurial > ~darius > hgwebdir.cgi > avr
annotate testavr.c @ 34:2b8278ec5adb
Work around FreeBSD setting CPU flags based on architectures
(-march=pentium-m doesn't work so well on AVR)
author | darius |
---|---|
date | Tue, 23 Oct 2007 10:52:50 +0930 |
parents | 48056516b3eb |
children | 25fa387ef7e9 |
rev | line source |
---|---|
0 | 1 /* |
9
7ed10c59ba06
Supply clock speed via the command line so 1wire-delay.h can use it.
darius
parents:
7
diff
changeset
|
2 * Test various AVR bits and pieces |
7ed10c59ba06
Supply clock speed via the command line so 1wire-delay.h can use it.
darius
parents:
7
diff
changeset
|
3 * |
7ed10c59ba06
Supply clock speed via the command line so 1wire-delay.h can use it.
darius
parents:
7
diff
changeset
|
4 * $Id$ |
7ed10c59ba06
Supply clock speed via the command line so 1wire-delay.h can use it.
darius
parents:
7
diff
changeset
|
5 * |
0 | 6 * Copyright (c) 2004 |
7 * Daniel O'Connor <darius@dons.net.au>. All rights reserved. | |
8 * | |
9 * Redistribution and use in source and binary forms, with or without | |
10 * modification, are permitted provided that the following conditions | |
11 * are met: | |
12 * 1. Redistributions of source code must retain the above copyright | |
13 * notice, this list of conditions and the following disclaimer. | |
14 * 2. Redistributions in binary form must reproduce the above copyright | |
15 * notice, this list of conditions and the following disclaimer in the | |
16 * documentation and/or other materials provided with the distribution. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
21 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
28 * SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include <avr/io.h> | |
32 #include <avr/interrupt.h> | |
33 #include <avr/pgmspace.h> | |
34 #include <string.h> | |
4 | 35 #include <ctype.h> |
13 | 36 #include <stdlib.h> |
24 | 37 #include <util/delay.h> |
0 | 38 |
39 #include "1wire.h" | |
24 | 40 #include "usb.h" |
0 | 41 |
42 #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) | |
24 | 43 #define UART_BAUD_RATE 38400 |
44 | |
45 void process_cmd(void); | |
0 | 46 |
47 void uart_putsP(const char *addr); | |
48 void uart_puts(const char *addr); | |
49 int uart_putc(char c); | |
13 | 50 void uart_puts_dec(uint8_t a, uint8_t l); |
51 void uart_puts_hex(uint8_t a); | |
24 | 52 char uart_getc(void); |
11 | 53 |
24 | 54 /* Receive buffer storage */ |
55 volatile struct { | |
56 char buf[40]; | |
57 uint8_t state; | |
58 uint8_t len; | |
59 } cmd = { | |
60 .state = 255, | |
61 .len = 0 | |
62 }; | |
4 | 63 |
24 | 64 /* Rx complete */ |
65 ISR(USART_RXC_vect) { | |
66 volatile char pit; | |
67 char c; | |
68 | |
69 while (UCSRA & _BV(RXC)) { | |
70 /* 255 means we're waiting for main to process the command, | |
71 just throw stuff away | |
72 */ | |
73 if (cmd.state == 255) { | |
74 pit = UDR; | |
75 continue; | |
76 } | |
77 c = UDR; | |
78 | |
79 /* End of line? */ | |
80 if (c == '\n' || c == '\r') { | |
81 cmd.buf[cmd.state + 1] = '\0'; | |
82 uart_putsP(PSTR("\n\r")); | |
83 cmd.len = cmd.state; | |
84 cmd.state = 255; | |
85 continue; | |
86 } | |
87 | |
88 /* Backspace/delete */ | |
89 if (c == 0x08 || c == 0x7f) { | |
90 if (cmd.state > 0) { | |
91 cmd.state--; | |
92 uart_putsP(PSTR("\010\040\010")); | |
4 | 93 } |
94 continue; | |
95 } | |
0 | 96 |
24 | 97 /* Anything unprintable just ignore it */ |
98 if (!isprint(c)) | |
99 continue; | |
100 | |
101 cmd.buf[cmd.state] = tolower(c); | |
102 | |
103 /* Echo back to the user */ | |
104 uart_putc(cmd.buf[cmd.state]); | |
105 | |
106 cmd.state++; | |
107 /* Over flow? */ | |
108 if (cmd.state == ((sizeof(cmd.buf) / sizeof(cmd.buf[0])) - 1)) { | |
109 uart_putsP(PSTR("\n\rLine too long")); | |
110 cmd.state = 0; | |
111 continue; | |
112 } | |
113 } | |
114 } | |
115 | |
116 /* Tx complete */ | |
117 ISR(USART_TXC_vect) { | |
4 | 118 |
24 | 119 } |
120 | |
121 int | |
122 main(void) { | |
123 /* Disable interrupts while we frob stuff */ | |
124 cli(); | |
125 | |
126 /* Disable JTAG (yes twice) */ | |
127 MCUCSR |= _BV(JTD); | |
128 MCUCSR |= _BV(JTD); | |
129 | |
130 /* USB data bus (7:0) */ | |
131 DDRA = 0x00; | |
132 PORTA = 0x00; | |
133 | |
134 /* USB control (3:0) */ | |
135 DDRB = 0x0e; | |
136 PORTB = 0x00; | |
137 | |
138 /* GPIO (0:7) */ | |
139 DDRC = 0xff; | |
140 PORTC = 0x00; | |
141 | |
142 /* GPIO (2:7) */ | |
143 DDRD = 0xfc; | |
30 | 144 PORTD = 0xfc; |
24 | 145 |
146 /* Init UART */ | |
147 UBRRH = UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) >> 8; | |
148 UBRRL = (uint8_t)UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU); | |
149 | |
150 /* Enable receiver and transmitter. Turn on transmit interrupts */ | |
151 UCSRA = 0; | |
152 UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); | |
153 UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); | |
154 uart_putsP(PSTR("\n\r\n\r===============\n\r" | |
155 "Inited!\n\r\n\r")); | |
156 | |
157 /* Ready to go! */ | |
158 sei(); | |
159 | |
160 usb_init(); | |
161 _delay_us(1000); | |
162 | |
163 uart_putsP(PSTR("> ")); | |
164 cmd.state = 0; | |
165 | |
166 /* Wait for user input or an "interrupt" */ | |
167 while (1) { | |
168 if (cmd.state == 255) { | |
169 process_cmd(); | |
170 uart_putsP(PSTR("> ")); | |
171 /* Allow new characters to be processed */ | |
172 cmd.state = 0; | |
173 } | |
174 | |
175 if (!(PINB & _BV(PB0))) | |
176 usb_intr(); | |
177 } | |
178 } | |
179 | |
180 void | |
181 process_cmd(void) { | |
182 uint8_t ROM[8]; | |
183 int8_t i, arg; | |
184 uint8_t crc, buf[9]; | |
185 int8_t temp; | |
186 uint16_t tfrac; | |
0 | 187 |
24 | 188 /* User just pressed enter */ |
189 if (cmd.len == 0) | |
190 return; | |
191 | |
192 if (cmd.buf[0] == '?') { | |
193 uart_putsP(PSTR("rs Reset and check for presence\n\r" | |
194 "sr Search the bus for ROMs\n\r" | |
195 "re Read a bit\n\r" | |
196 "rb Read a byte\n\r" | |
197 "wr bit Write a bit\n\r" | |
198 "wb byte Write a byte (hex)\n\r" | |
199 "wc cmd [ROMID] Write command\n\r" | |
200 "te ROMID Read the temperature from a DS1820\n\r" | |
201 "in port Read from a port\n\r" | |
202 "out port val Write to a port\n\r" | |
203 "ddr port [val] Read/write DDR for a port\n\r")); | |
204 | |
205 return; | |
206 } | |
207 | |
208 i = strlen((char *)cmd.buf); | |
209 if (cmd.len < 2) | |
210 goto badcmd; | |
211 | |
212 if (cmd.buf[0] == 'r' && cmd.buf[1] == 's') { | |
213 uart_putsP(PSTR("Resetting... ")); | |
4 | 214 |
24 | 215 if (OWTouchReset() == 1) |
216 uart_putsP(PSTR("No presence pulse found\n\r")); | |
217 else | |
218 uart_putsP(PSTR("Presence pulse found\n\r")); | |
219 } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'e') { | |
220 if (OWReadBit()) | |
221 uart_putsP(PSTR("Read a 1\n\r")); | |
222 else | |
223 uart_putsP(PSTR("Read a 0\n\r")); | |
224 } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'b') { | |
225 uart_putsP(PSTR("Read a 0x")); | |
226 uart_puts_hex(OWReadByte()); | |
227 uart_putsP(PSTR("\n\r")); | |
228 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'r') { | |
229 arg = strtol((char *)cmd.buf + 3, (char **)NULL, 10); | |
230 OWWriteBit(arg); | |
231 uart_putsP(PSTR("Wrote a ")); | |
232 if (arg) | |
233 uart_putsP(PSTR("1\n\r")); | |
234 else | |
235 uart_putsP(PSTR("0\n\r")); | |
236 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'b') { | |
237 arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); | |
238 OWWriteByte(arg); | |
239 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'c') { | |
240 if (cmd.len < 5) { | |
241 uart_putsP(PSTR("No arguments\n\r")); | |
242 return; | |
243 } | |
244 | |
245 arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); | |
246 if (arg == 0) { | |
247 uart_putsP(PSTR("Unparseable command\n\r")); | |
248 return; | |
249 } | |
13 | 250 |
24 | 251 if (i == 5) { |
252 OWSendCmd(NULL, arg); | |
253 return; | |
254 } | |
4 | 255 |
24 | 256 if (i < 29) { |
257 uart_putsP(PSTR("Can't parse ROM ID\n\r")); | |
258 return; | |
259 } | |
260 for (i = 0; i < 8; i++) | |
261 ROM[i] = (int)strtol((char *)cmd.buf + 6 + (3 * i), (char **)NULL, 16); | |
262 | |
263 OWSendCmd(ROM, arg); | |
264 } else if (cmd.buf[0] == 't' && cmd.buf[1] == 'e') { | |
265 if (cmd.len < 26) { | |
266 uart_putsP(PSTR("Unable to parse ROM ID\n\r")); | |
267 return; | |
268 } | |
269 | |
270 for (i = 0; i < 8; i++) | |
271 ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); | |
272 | |
273 if (ROM[0] != OW_FAMILY_TEMP) { | |
274 uart_putsP(PSTR("ROM specified isn't a temperature sensor\n\r")); | |
275 return; | |
276 } | |
4 | 277 |
24 | 278 OWSendCmd(ROM, OW_CONVERTT_CMD); |
279 i = 0; | |
280 while (OWReadBit() == 0) { | |
281 i++; | |
282 } | |
283 OWSendCmd(ROM, OW_RD_SCR_CMD); | |
284 crc = 0; | |
285 for (i = 0; i < 9; i++) { | |
286 buf[i] = OWReadByte(); | |
287 if (i < 8) | |
288 OWCRC(buf[i], &crc); | |
289 } | |
290 | |
291 if (crc != buf[8]) { | |
292 uart_putsP(PSTR("CRC mismatch\n\r")); | |
293 return; | |
294 } | |
4 | 295 |
13 | 296 #if 0 |
24 | 297 uart_putsP(PSTR("temperature ")); |
298 uart_puts_dec(temp >> 4, 0); | |
299 uart_putsP(PSTR(".")); | |
300 uart_puts_dec((temp << 12) / 6553, 0); | |
301 uart_putsP(PSTR("\n\r")); | |
13 | 302 #else |
24 | 303 /* 0 Temperature LSB |
304 * 1 Temperature MSB | |
305 * 2 Th | |
306 * 3 Tl | |
307 * 4 Reserved | |
308 * 5 Reserved | |
309 * 6 Count Remain | |
310 * 7 Count per C | |
311 * 8 CRC | |
312 */ | |
13 | 313 #if 0 |
24 | 314 for (i = 0; i < 9; i++) { |
315 uart_puts_dec(buf[i], 0); | |
316 uart_putsP(PSTR("\n\r")); | |
317 } | |
13 | 318 #endif |
24 | 319 temp = buf[0]; |
320 if (buf[1] & 0x80) | |
321 temp -= 256; | |
322 temp >>= 1; | |
13 | 323 |
24 | 324 tfrac = buf[7] - buf[6]; |
325 tfrac *= (uint16_t)100; | |
326 tfrac /= buf[7]; | |
327 tfrac += 75; | |
328 if (tfrac < 100) { | |
329 temp--; | |
330 } else { | |
331 tfrac -= 100; | |
332 } | |
13 | 333 |
24 | 334 if (temp < 0){ |
335 uart_putc('-'); | |
336 uart_puts_dec(-temp, 0); | |
337 } else | |
338 uart_puts_dec(temp, 0); | |
339 uart_putsP(PSTR(".")); | |
340 uart_puts_dec(tfrac, 1); | |
341 uart_putsP(PSTR("\n\r")); | |
13 | 342 |
343 #endif | |
24 | 344 } else if (cmd.buf[0] == 's' && cmd.buf[1] == 'r') { |
345 memset(ROM, 0, 8); | |
10 | 346 |
24 | 347 i = OWFirst(ROM, 1, 0); |
348 do { | |
349 switch (i) { | |
10 | 350 case OW_BADWIRE: |
16 | 351 uart_putsP(PSTR("Presence pulse, but no module found, bad module/cabling?\n\r")); |
10 | 352 break; |
353 | |
354 case OW_NOPRESENCE: | |
16 | 355 uart_putsP(PSTR("No presence pulse found\n\r")); |
10 | 356 break; |
357 | |
358 case OW_BADCRC: | |
359 uart_putsP(PSTR("Bad CRC\n\r")); | |
360 break; | |
361 | |
362 case OW_NOMODULES: | |
363 case OW_FOUND: | |
364 break; | |
365 | |
366 default: | |
367 uart_putsP(PSTR("Unknown error from 1 wire library\n\r")); | |
368 break; | |
24 | 369 } |
10 | 370 |
24 | 371 if (i != OW_FOUND) |
372 break; | |
13 | 373 |
24 | 374 for (i = 0; i < 7; i++) { |
375 uart_puts_hex(ROM[i]); | |
376 uart_putc(':'); | |
377 } | |
378 uart_puts_hex(ROM[7]); | |
379 uart_putsP(PSTR("\n\r")); | |
10 | 380 |
24 | 381 i = OWNext(ROM, 1, 0); |
382 } while (1); | |
383 } else if (cmd.buf[0] == 'i' && cmd.buf[1] == 'n') { | |
384 switch (tolower(cmd.buf[3])) { | |
385 case 'a': | |
386 crc = PINA; | |
387 break; | |
388 | |
389 case 'b': | |
390 crc = PINB; | |
391 break; | |
392 | |
393 case 'c': | |
394 crc = PINC; | |
395 break; | |
396 | |
397 case 'd': | |
398 crc = PIND; | |
399 break; | |
400 | |
401 default: | |
402 uart_putsP(PSTR("Unknown port\n\r")); | |
403 return; | |
0 | 404 } |
24 | 405 uart_putsP(PSTR("0x")); |
406 uart_puts_hex(crc); | |
407 uart_putsP(PSTR("\n\r")); | |
408 } else if (cmd.buf[0] == 'o' && cmd.buf[1] == 'u') { | |
409 crc = strtol((char *)cmd.buf + 8, (char **)NULL, 16); | |
410 switch (tolower(cmd.buf[4])) { | |
411 case 'a': | |
412 PORTA = crc; | |
413 break; | |
414 | |
415 case 'b': | |
416 PORTB = crc; | |
417 break; | |
418 | |
419 case 'c': | |
420 PORTC = crc; | |
421 break; | |
422 | |
423 case 'd': | |
424 PORTD = crc; | |
425 break; | |
426 | |
427 default: | |
428 uart_putsP(PSTR("Unknown port\n\r")); | |
429 return; | |
430 } | |
431 uart_putsP(PSTR("0x")); | |
432 uart_puts_hex(crc); | |
433 uart_putsP(PSTR("\n\r")); | |
434 } else if (cmd.buf[0] == 'u' && cmd.buf[1] == 's') { | |
435 usb_gendata(); | |
436 } else { | |
437 badcmd: | |
438 uart_putsP(PSTR("Unknown command, ? for a list\n\r")); | |
0 | 439 } |
24 | 440 } |
0 | 441 |
442 int | |
443 uart_putc(char c) { | |
24 | 444 loop_until_bit_is_set(UCSRA, UDRE); |
17
a58b41b7d15c
Covert to a later version of avr-libc. Stuff like not using inb/outb,
darius
parents:
16
diff
changeset
|
445 UDR = c; |
0 | 446 |
447 return(0); | |
448 } | |
449 | |
450 void | |
451 uart_putsP(const char *addr) { | |
452 char c; | |
453 | |
17
a58b41b7d15c
Covert to a later version of avr-libc. Stuff like not using inb/outb,
darius
parents:
16
diff
changeset
|
454 while ((c = pgm_read_byte_near(addr++))) |
0 | 455 uart_putc(c); |
456 } | |
457 | |
458 void | |
459 uart_puts(const char *addr) { | |
460 while (*addr) | |
461 uart_putc(*addr++); | |
462 } | |
463 | |
13 | 464 void |
465 uart_puts_dec(uint8_t a, uint8_t l) { | |
466 char s[4]; | |
467 | |
468 if (l && a < 10) | |
469 uart_putsP(PSTR("0")); | |
470 uart_puts(utoa(a, s, 10)); | |
471 } | |
472 | |
473 void | |
474 uart_puts_hex(uint8_t a) { | |
475 char s[3]; | |
476 | |
477 if (a < 0x10) | |
478 uart_putc('0'); | |
479 | |
480 uart_puts(utoa(a, s, 16)); | |
481 } | |
482 | |
24 | 483 char |
0 | 484 uart_getc(void) { |
24 | 485 while (!(UCSRA & _BV(RXC))) |
0 | 486 ; |
487 | |
17
a58b41b7d15c
Covert to a later version of avr-libc. Stuff like not using inb/outb,
darius
parents:
16
diff
changeset
|
488 return (UDR); |
0 | 489 } |
4 | 490 |