Mercurial > ~darius > hgwebdir.cgi > tempctrl
annotate testavr.c @ 48:94f71ddb0cda
Move declaration of error table up with the function declarations.
author | darius@Inchoate |
---|---|
date | Wed, 29 Oct 2008 16:03:16 +1030 |
parents | 13a68734348b |
children | cb184206344d |
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 * |
41 | 4 * Copyright (c) 2008 |
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 <avr/io.h> | |
30 #include <avr/interrupt.h> | |
31 #include <avr/pgmspace.h> | |
41 | 32 #include <stdio.h> |
0 | 33 #include <string.h> |
4 | 34 #include <ctype.h> |
13 | 35 #include <stdlib.h> |
24 | 36 #include <util/delay.h> |
47 | 37 #include <avr/wdt.h> |
0 | 38 |
41 | 39 #include "cons.h" |
0 | 40 #include "1wire.h" |
37 | 41 #ifdef WITHUSB |
24 | 42 #include "usb.h" |
37 | 43 #endif |
41 | 44 #include "tempctrl.h" |
24 | 45 |
47 | 46 /* |
47 * Mirror of the MCUCSR register, taken early during startup. | |
48 */ | |
49 uint8_t mcucsr __attribute__((section(".noinit"))); | |
50 | |
24 | 51 void process_cmd(void); |
0 | 52 |
47 | 53 /* |
54 * Read out and reset MCUCSR early during startup. | |
55 */ | |
56 void handle_mcucsr(void) | |
57 __attribute__((section(".init3"))) | |
58 __attribute__((naked)); | |
59 void handle_mcucsr(void) { | |
60 mcucsr = MCUCSR; | |
61 MCUCSR = 0; | |
62 } | |
63 | |
24 | 64 int |
65 main(void) { | |
66 /* Disable interrupts while we frob stuff */ | |
67 cli(); | |
68 | |
41 | 69 #if 0 |
24 | 70 /* Disable JTAG (yes twice) */ |
71 MCUCSR |= _BV(JTD); | |
72 MCUCSR |= _BV(JTD); | |
37 | 73 #endif |
74 | |
75 #ifdef WITHUSB | |
24 | 76 /* USB data bus (7:0) */ |
77 DDRA = 0x00; | |
78 PORTA = 0x00; | |
79 | |
37 | 80 /* USB control (4:0) */ |
81 DDRB = 0x0d; | |
24 | 82 PORTB = 0x00; |
37 | 83 #else |
84 DDRA = 0xff; | |
85 PORTA = 0x00; | |
86 #endif | |
24 | 87 /* GPIO (0:7) */ |
88 DDRC = 0xff; | |
89 PORTC = 0x00; | |
90 | |
37 | 91 /* USART (0:1), IDBus (2:5), 485 (6:6), GPIO (7:7) */ |
92 DDRD = 0xf7; | |
93 PORTD = 0xf7; | |
94 | |
95 /* Set up the one wire stuff */ | |
96 OWInit(); | |
24 | 97 |
98 /* Init UART */ | |
41 | 99 cons_init(); |
24 | 100 |
41 | 101 printf_P(PSTR("\r\n\r\n===============\r\n" |
102 "Inited!\r\n\r\n")); | |
24 | 103 |
47 | 104 if ((mcucsr & _BV(PORF)) == _BV(PORF)) |
105 printf_P(PSTR("Power on reset\r\n")); | |
106 | |
107 if ((mcucsr & _BV(EXTRF)) == _BV(EXTRF)) | |
108 printf_P(PSTR("External reset\r\n")); | |
109 | |
110 if ((mcucsr & _BV(BORF)) == _BV(BORF)) | |
111 printf_P(PSTR("Brown-out reset\r\n")); | |
112 | |
113 if ((mcucsr & _BV(WDRF)) == _BV(WDRF)) | |
114 printf_P(PSTR("Watchdog reset\r\n")); | |
115 | |
116 if ((mcucsr & _BV(JTRF)) == _BV(JTRF)) | |
117 printf_P(PSTR("JTAG reset\r\n")); | |
118 | |
41 | 119 tempctrl_init(); |
120 | |
24 | 121 /* Ready to go! */ |
122 sei(); | |
123 | |
47 | 124 /* |
125 * Enable the watchdog with the largest prescaler. Will cause a | |
126 * watchdog reset after approximately 2 s @ Vcc = 5 V | |
127 * | |
128 * Gets reset in the loop below and in the tempctrl.c timer IRQ | |
129 */ | |
130 wdt_enable(WDTO_2S); | |
131 | |
37 | 132 #ifdef WITHUSB |
41 | 133 printf_P(PSTR("Calling usb_init\r\n")); |
24 | 134 usb_init(); |
41 | 135 printf_P(PSTR("done\r\n")); |
136 _delay_us(1000); | |
37 | 137 #endif |
41 | 138 printf_P(PSTR("> ")); |
24 | 139 cmd.state = 0; |
140 | |
141 /* Wait for user input or an "interrupt" */ | |
142 while (1) { | |
47 | 143 wdt_reset(); |
144 | |
41 | 145 tempctrl_update(); |
146 | |
24 | 147 if (cmd.state == 255) { |
148 process_cmd(); | |
41 | 149 printf_P(PSTR("> ")); |
24 | 150 /* Allow new characters to be processed */ |
151 cmd.state = 0; | |
152 } | |
153 | |
37 | 154 #ifdef WITHUSB |
155 if (!(PDICTL & _BV(PDIINT))) | |
24 | 156 usb_intr(); |
37 | 157 #endif |
24 | 158 } |
159 } | |
160 | |
161 void | |
162 process_cmd(void) { | |
163 uint8_t ROM[8]; | |
164 int8_t i, arg; | |
165 uint8_t crc, buf[9]; | |
166 int8_t temp; | |
167 uint16_t tfrac; | |
0 | 168 |
24 | 169 /* User just pressed enter */ |
170 if (cmd.len == 0) | |
171 return; | |
172 | |
173 if (cmd.buf[0] == '?') { | |
41 | 174 printf_P(PSTR("rs Reset and check for presence\r\n" |
175 "sr Search the bus for ROMs\r\n" | |
176 "re Read a bit\r\n" | |
177 "rb Read a byte\r\n" | |
178 "wr bit Write a bit\r\n" | |
179 "wb byte Write a byte (hex)\r\n" | |
180 "wc cmd [ROMID] Write command\r\n" | |
181 "te ROMID Read the temperature from a DS1820\r\n" | |
182 "in port Read from a port\r\n" | |
183 "out port val Write to a port\r\n" | |
184 "ddr port [val] Read/write DDR for a port\r\n" | |
185 "tc ... Temperature control related (tc help for more)\r\n")); | |
186 | |
24 | 187 return; |
188 } | |
189 | |
190 i = strlen((char *)cmd.buf); | |
191 if (cmd.len < 2) | |
192 goto badcmd; | |
193 | |
194 if (cmd.buf[0] == 'r' && cmd.buf[1] == 's') { | |
41 | 195 printf_P(PSTR("Resetting... ")); |
4 | 196 |
24 | 197 if (OWTouchReset() == 1) |
41 | 198 printf_P(PSTR("No presence pulse found\r\n")); |
24 | 199 else |
41 | 200 printf_P(PSTR("Presence pulse found\r\n")); |
24 | 201 } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'e') { |
202 if (OWReadBit()) | |
41 | 203 printf_P(PSTR("Read a 1\r\n")); |
24 | 204 else |
41 | 205 printf_P(PSTR("Read a 0\r\n")); |
24 | 206 } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'b') { |
41 | 207 printf_P(PSTR("Read a 0x%02x\r\n"), OWReadByte()); |
24 | 208 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'r') { |
209 arg = strtol((char *)cmd.buf + 3, (char **)NULL, 10); | |
210 OWWriteBit(arg); | |
41 | 211 printf_P(PSTR("Wrote a %c\r\n"), arg ? '1' : '0'); |
24 | 212 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'b') { |
213 arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); | |
214 OWWriteByte(arg); | |
37 | 215 } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 't') { |
216 if (cmd.len < 26) { | |
41 | 217 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
37 | 218 return; |
219 } | |
220 | |
221 if (OWTouchReset() != 0) { | |
41 | 222 printf_P(PSTR("No presence\r\n")); |
37 | 223 return; |
224 } | |
225 | |
226 for (i = 0; i < 8; i++) | |
227 ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); | |
228 | |
229 if (ROM[0] != OW_FAMILY_ROM) { | |
41 | 230 printf_P(PSTR("ROM specified isn't a DS2502\r\n")); |
37 | 231 return; |
232 } | |
233 | |
234 if (OWTouchReset() != 0) { | |
41 | 235 printf_P(PSTR("No presence\r\n")); |
37 | 236 return; |
237 } | |
238 | |
239 crc = 0; | |
240 | |
241 OWCRC(OW_READ_STATUS, &crc); | |
242 OWSendCmd(ROM, OW_READ_STATUS); | |
243 | |
244 OWWriteByte(0x00); | |
245 OWCRC(0x00, &crc); | |
246 | |
247 OWWriteByte(0x00); | |
248 OWCRC(0x00, &crc); | |
249 | |
250 if (crc != OWReadByte()) { | |
41 | 251 printf_P(PSTR("CRC mismatch on command & address\r\n")); |
37 | 252 return; |
253 } | |
254 | |
255 crc = 0; | |
256 for (i = 0; i < 8; i++) { | |
257 temp = OWReadByte(); | |
41 | 258 printf_P(PSTR("%02x "), temp); |
37 | 259 OWCRC(temp, &crc); |
260 } | |
41 | 261 printf_P(PSTR("\r\n")); |
37 | 262 if (crc != OWReadByte()) { |
41 | 263 printf_P(PSTR("CRC mismatch on data\r\n")); |
37 | 264 return; |
265 } | |
266 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'e') { | |
267 if (cmd.len < 26) { | |
41 | 268 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
37 | 269 return; |
270 } | |
271 | |
272 for (i = 0; i < 8; i++) | |
273 ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); | |
274 | |
275 if (ROM[0] != OW_FAMILY_ROM) { | |
41 | 276 printf_P(PSTR("ROM specified isn't a ROM\r\n")); |
37 | 277 return; |
278 } | |
279 | |
280 buf[0] = (int)strtol((char *)cmd.buf + 27, (char **)NULL, 16); /* Address */ | |
281 buf[1] = (int)strtol((char *)cmd.buf + 30, (char **)NULL, 16); /* Data .. */ | |
282 buf[2] = (int)strtol((char *)cmd.buf + 33, (char **)NULL, 16); | |
283 | |
284 if (OWTouchReset() != 0) { | |
41 | 285 printf_P(PSTR("No presence\r\n")); |
37 | 286 return; |
287 } | |
288 | |
289 i = OWProgROM(ROM, buf[0], 2, &buf[1], 0, 0); | |
41 | 290 printf_P(PSTR("OWProgROM returned %d\r\n"), i); |
37 | 291 } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'r') { |
292 if (cmd.len < 26) { | |
41 | 293 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
37 | 294 return; |
295 } | |
296 | |
297 for (i = 0; i < 8; i++) | |
298 ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); | |
299 | |
300 if (ROM[0] != OW_FAMILY_ROM) { | |
41 | 301 printf_P(PSTR("ROM specified isn't a ROM\r\n")); |
37 | 302 return; |
303 } | |
304 | |
305 crc = 0; | |
306 OWSendCmd(ROM, OW_READ_MEMORY); | |
307 OWCRC(OW_READ_MEMORY, &crc); | |
308 | |
309 OWWriteByte(0x00); | |
310 OWCRC(0x00, &crc); | |
311 | |
312 OWWriteByte(0x00); | |
313 OWCRC(0x00, &crc); | |
314 | |
315 if (crc != OWReadByte()) { | |
41 | 316 printf_P(PSTR("CRC mismatch on command & address\r\n")); |
37 | 317 return; |
318 } | |
319 | |
320 crc = 0; | |
321 for (buf[0] = 0; buf[0] < 128; buf[0]++) { | |
322 buf[1] = OWReadByte(); | |
323 if (buf[0] > 0) { | |
324 if (buf[0] % 16 != 0) | |
41 | 325 printf_P(PSTR(" ")); |
37 | 326 else |
41 | 327 printf_P(PSTR("\r\n")); |
37 | 328 } |
329 | |
41 | 330 printf_P(PSTR("%02x"), buf[1]); |
37 | 331 OWCRC(buf[1], &crc); |
332 } | |
41 | 333 printf_P(PSTR("\r\n")); |
37 | 334 if (crc != OWReadByte()) { |
41 | 335 printf_P(PSTR("CRC mismatch on data\r\n")); |
37 | 336 return; |
337 } | |
338 | |
24 | 339 } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'c') { |
340 if (cmd.len < 5) { | |
41 | 341 printf_P(PSTR("No arguments\r\n")); |
24 | 342 return; |
343 } | |
344 | |
345 arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); | |
346 if (arg == 0) { | |
41 | 347 printf_P(PSTR("Unparseable command\r\n")); |
24 | 348 return; |
349 } | |
13 | 350 |
24 | 351 if (i == 5) { |
352 OWSendCmd(NULL, arg); | |
353 return; | |
354 } | |
4 | 355 |
24 | 356 if (i < 29) { |
41 | 357 printf_P(PSTR("Can't parse ROM ID\r\n")); |
24 | 358 return; |
359 } | |
360 for (i = 0; i < 8; i++) | |
361 ROM[i] = (int)strtol((char *)cmd.buf + 6 + (3 * i), (char **)NULL, 16); | |
362 | |
363 OWSendCmd(ROM, arg); | |
364 } else if (cmd.buf[0] == 't' && cmd.buf[1] == 'e') { | |
365 if (cmd.len < 26) { | |
41 | 366 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
24 | 367 return; |
368 } | |
369 | |
370 for (i = 0; i < 8; i++) | |
371 ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); | |
372 | |
373 if (ROM[0] != OW_FAMILY_TEMP) { | |
41 | 374 printf_P(PSTR("ROM specified isn't a temperature sensor\r\n")); |
24 | 375 return; |
376 } | |
4 | 377 |
24 | 378 OWSendCmd(ROM, OW_CONVERTT_CMD); |
379 i = 0; | |
37 | 380 /* Wait for the conversion */ |
41 | 381 while (OWReadBit() == 0) |
382 i = 1; | |
383 | |
384 | |
24 | 385 OWSendCmd(ROM, OW_RD_SCR_CMD); |
386 crc = 0; | |
387 for (i = 0; i < 9; i++) { | |
388 buf[i] = OWReadByte(); | |
389 if (i < 8) | |
390 OWCRC(buf[i], &crc); | |
391 } | |
392 | |
393 if (crc != buf[8]) { | |
41 | 394 printf_P(PSTR("CRC mismatch\r\n")); |
24 | 395 return; |
396 } | |
4 | 397 |
24 | 398 /* 0 Temperature LSB |
399 * 1 Temperature MSB | |
400 * 2 Th | |
401 * 3 Tl | |
402 * 4 Reserved | |
403 * 5 Reserved | |
404 * 6 Count Remain | |
405 * 7 Count per C | |
406 * 8 CRC | |
407 */ | |
13 | 408 #if 0 |
41 | 409 for (i = 0; i < 9; i++) |
410 printf_P(PSTR("%d\r\n"), buf[i]); | |
13 | 411 #endif |
24 | 412 temp = buf[0]; |
413 if (buf[1] & 0x80) | |
414 temp -= 256; | |
415 temp >>= 1; | |
13 | 416 |
24 | 417 tfrac = buf[7] - buf[6]; |
418 tfrac *= (uint16_t)100; | |
419 tfrac /= buf[7]; | |
420 tfrac += 75; | |
421 if (tfrac < 100) { | |
422 temp--; | |
423 } else { | |
424 tfrac -= 100; | |
425 } | |
13 | 426 |
41 | 427 printf_P(PSTR("%d.%02d\r\n"), temp, tfrac); |
24 | 428 } else if (cmd.buf[0] == 's' && cmd.buf[1] == 'r') { |
429 memset(ROM, 0, 8); | |
10 | 430 |
24 | 431 i = OWFirst(ROM, 1, 0); |
432 do { | |
433 switch (i) { | |
10 | 434 case OW_BADWIRE: |
41 | 435 printf_P(PSTR("Presence pulse, but no module found, bad module/cabling?\r\n")); |
10 | 436 break; |
437 | |
438 case OW_NOPRESENCE: | |
41 | 439 printf_P(PSTR("No presence pulse found\r\n")); |
10 | 440 break; |
441 | |
442 case OW_BADCRC: | |
41 | 443 printf_P(PSTR("Bad CRC\r\n")); |
10 | 444 break; |
445 | |
446 case OW_NOMODULES: | |
447 case OW_FOUND: | |
448 break; | |
449 | |
450 default: | |
41 | 451 printf_P(PSTR("Unknown error from 1 wire library\r\n")); |
10 | 452 break; |
24 | 453 } |
10 | 454 |
24 | 455 if (i != OW_FOUND) |
456 break; | |
13 | 457 |
41 | 458 for (i = 0; i < 8; i++) |
459 printf_P(PSTR("%02x%S"), ROM[i], i == 7 ? PSTR("\r\n") : PSTR(":")); | |
10 | 460 |
24 | 461 i = OWNext(ROM, 1, 0); |
462 } while (1); | |
463 } else if (cmd.buf[0] == 'i' && cmd.buf[1] == 'n') { | |
464 switch (tolower(cmd.buf[3])) { | |
465 case 'a': | |
466 crc = PINA; | |
467 break; | |
468 | |
469 case 'b': | |
470 crc = PINB; | |
471 break; | |
472 | |
473 case 'c': | |
474 crc = PINC; | |
475 break; | |
476 | |
477 case 'd': | |
478 crc = PIND; | |
479 break; | |
480 | |
481 default: | |
41 | 482 printf_P(PSTR("Unknown port\r\n")); |
24 | 483 return; |
0 | 484 } |
41 | 485 printf_P(PSTR("0x%02x\r\n"), crc); |
24 | 486 } else if (cmd.buf[0] == 'o' && cmd.buf[1] == 'u') { |
487 crc = strtol((char *)cmd.buf + 8, (char **)NULL, 16); | |
488 switch (tolower(cmd.buf[4])) { | |
489 case 'a': | |
490 PORTA = crc; | |
491 break; | |
492 | |
493 case 'b': | |
494 PORTB = crc; | |
495 break; | |
496 | |
497 case 'c': | |
498 PORTC = crc; | |
499 break; | |
500 | |
501 case 'd': | |
502 PORTD = crc; | |
503 break; | |
504 | |
505 default: | |
41 | 506 printf_P(PSTR("Unknown port\r\n")); |
24 | 507 return; |
508 } | |
41 | 509 printf_P(PSTR("PORT%c <= 0x%02x\r\n"), toupper(cmd.buf[4]), crc); |
37 | 510 } else if (cmd.buf[0] == 'd' && cmd.buf[1] == 'd') { |
511 crc = strtol((char *)cmd.buf + 8, (char **)NULL, 16); | |
512 switch (tolower(cmd.buf[4])) { | |
513 case 'a': | |
514 DDRA = crc; | |
515 break; | |
516 | |
517 case 'b': | |
518 DDRB = crc; | |
519 break; | |
520 | |
521 case 'c': | |
522 DDRC = crc; | |
523 break; | |
524 | |
525 case 'd': | |
526 DDRD = crc; | |
527 break; | |
528 | |
529 default: | |
41 | 530 printf_P(PSTR("Unknown port\r\n")); |
37 | 531 return; |
532 } | |
41 | 533 printf_P(PSTR("0x%02x\r\n"), crc); |
534 } else if (cmd.buf[0] == 't' && cmd.buf[1] == 'c') { | |
535 tempctrl_cmd((char *)cmd.buf); | |
37 | 536 #ifdef WITHUSB |
24 | 537 } else if (cmd.buf[0] == 'u' && cmd.buf[1] == 's') { |
538 usb_gendata(); | |
37 | 539 #endif |
24 | 540 } else { |
541 badcmd: | |
41 | 542 printf_P(PSTR("Unknown command, ? for a list\r\n")); |
0 | 543 } |
24 | 544 } |
0 | 545 |
546 |