Mercurial > ~darius > hgwebdir.cgi > avr
view testavr.c @ 41:5898fba6593c
Add temperature control.
- Split out console stuff to cons.[ch]. Set up stdio so we can use printf etc.
- Use \r\n as the line terminator consistently.
- Add OWGetTemp to get temperatures from a device.
- Load/save settings in EEPROM, defaults loaded from flash.
Nearly feature complete except you can't edit ROM IDs without a programming tool :)
(To be fixed)
Needs more testing.
author | darius@inchoate.localdomain |
---|---|
date | Sun, 06 Jul 2008 22:19:53 +0930 |
parents | 0a148f362097 |
children | 13a68734348b |
line wrap: on
line source
/* * Test various AVR bits and pieces * * Copyright (c) 2008 * Daniel O'Connor <darius@dons.net.au>. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <util/delay.h> #include "cons.h" #include "1wire.h" #ifdef WITHUSB #include "usb.h" #endif #include "tempctrl.h" void process_cmd(void); int main(void) { /* Disable interrupts while we frob stuff */ cli(); #if 0 /* Disable JTAG (yes twice) */ MCUCSR |= _BV(JTD); MCUCSR |= _BV(JTD); #endif #ifdef WITHUSB /* USB data bus (7:0) */ DDRA = 0x00; PORTA = 0x00; /* USB control (4:0) */ DDRB = 0x0d; PORTB = 0x00; #else DDRA = 0xff; PORTA = 0x00; #endif /* GPIO (0:7) */ DDRC = 0xff; PORTC = 0x00; /* USART (0:1), IDBus (2:5), 485 (6:6), GPIO (7:7) */ DDRD = 0xf7; PORTD = 0xf7; /* Set up the one wire stuff */ OWInit(); /* Init UART */ cons_init(); printf_P(PSTR("\r\n\r\n===============\r\n" "Inited!\r\n\r\n")); tempctrl_init(); /* Ready to go! */ sei(); #if 0 DDRA = 0xff; DDRC = 0xff; while (1) { printf_P(PSTR("1\r\n")); PORTA = 0xff; printf_P(PSTR("2\r\n")); PORTC = 0x00; printf_P(PSTR("3\r\n")); _delay_us(1); printf_P(PSTR("4\r\n")); PORTA = 0x80; printf_P(PSTR("5\r\n")); PORTC = 0xff; printf_P(PSTR("6\r\n")); } #endif #ifdef WITHUSB printf_P(PSTR("Calling usb_init\r\n")); usb_init(); printf_P(PSTR("done\r\n")); _delay_us(1000); #endif printf_P(PSTR("> ")); cmd.state = 0; /* Wait for user input or an "interrupt" */ while (1) { tempctrl_update(); if (cmd.state == 255) { process_cmd(); printf_P(PSTR("> ")); /* Allow new characters to be processed */ cmd.state = 0; } #ifdef WITHUSB if (!(PDICTL & _BV(PDIINT))) usb_intr(); #endif } } void process_cmd(void) { uint8_t ROM[8]; int8_t i, arg; uint8_t crc, buf[9]; int8_t temp; uint16_t tfrac; /* User just pressed enter */ if (cmd.len == 0) return; if (cmd.buf[0] == '?') { printf_P(PSTR("rs Reset and check for presence\r\n" "sr Search the bus for ROMs\r\n" "re Read a bit\r\n" "rb Read a byte\r\n" "wr bit Write a bit\r\n" "wb byte Write a byte (hex)\r\n" "wc cmd [ROMID] Write command\r\n" "te ROMID Read the temperature from a DS1820\r\n" "in port Read from a port\r\n" "out port val Write to a port\r\n" "ddr port [val] Read/write DDR for a port\r\n" "tc ... Temperature control related (tc help for more)\r\n")); return; } i = strlen((char *)cmd.buf); if (cmd.len < 2) goto badcmd; if (cmd.buf[0] == 'r' && cmd.buf[1] == 's') { printf_P(PSTR("Resetting... ")); if (OWTouchReset() == 1) printf_P(PSTR("No presence pulse found\r\n")); else printf_P(PSTR("Presence pulse found\r\n")); } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'e') { if (OWReadBit()) printf_P(PSTR("Read a 1\r\n")); else printf_P(PSTR("Read a 0\r\n")); } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'b') { printf_P(PSTR("Read a 0x%02x\r\n"), OWReadByte()); } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'r') { arg = strtol((char *)cmd.buf + 3, (char **)NULL, 10); OWWriteBit(arg); printf_P(PSTR("Wrote a %c\r\n"), arg ? '1' : '0'); } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'b') { arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); OWWriteByte(arg); } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 't') { if (cmd.len < 26) { printf_P(PSTR("Unable to parse ROM ID\r\n")); return; } if (OWTouchReset() != 0) { printf_P(PSTR("No presence\r\n")); return; } for (i = 0; i < 8; i++) ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); if (ROM[0] != OW_FAMILY_ROM) { printf_P(PSTR("ROM specified isn't a DS2502\r\n")); return; } if (OWTouchReset() != 0) { printf_P(PSTR("No presence\r\n")); return; } crc = 0; OWCRC(OW_READ_STATUS, &crc); OWSendCmd(ROM, OW_READ_STATUS); OWWriteByte(0x00); OWCRC(0x00, &crc); OWWriteByte(0x00); OWCRC(0x00, &crc); if (crc != OWReadByte()) { printf_P(PSTR("CRC mismatch on command & address\r\n")); return; } crc = 0; for (i = 0; i < 8; i++) { temp = OWReadByte(); printf_P(PSTR("%02x "), temp); OWCRC(temp, &crc); } printf_P(PSTR("\r\n")); if (crc != OWReadByte()) { printf_P(PSTR("CRC mismatch on data\r\n")); return; } } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'e') { if (cmd.len < 26) { printf_P(PSTR("Unable to parse ROM ID\r\n")); return; } for (i = 0; i < 8; i++) ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); if (ROM[0] != OW_FAMILY_ROM) { printf_P(PSTR("ROM specified isn't a ROM\r\n")); return; } buf[0] = (int)strtol((char *)cmd.buf + 27, (char **)NULL, 16); /* Address */ buf[1] = (int)strtol((char *)cmd.buf + 30, (char **)NULL, 16); /* Data .. */ buf[2] = (int)strtol((char *)cmd.buf + 33, (char **)NULL, 16); if (OWTouchReset() != 0) { printf_P(PSTR("No presence\r\n")); return; } i = OWProgROM(ROM, buf[0], 2, &buf[1], 0, 0); printf_P(PSTR("OWProgROM returned %d\r\n"), i); } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'r') { if (cmd.len < 26) { printf_P(PSTR("Unable to parse ROM ID\r\n")); return; } for (i = 0; i < 8; i++) ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); if (ROM[0] != OW_FAMILY_ROM) { printf_P(PSTR("ROM specified isn't a ROM\r\n")); return; } crc = 0; OWSendCmd(ROM, OW_READ_MEMORY); OWCRC(OW_READ_MEMORY, &crc); OWWriteByte(0x00); OWCRC(0x00, &crc); OWWriteByte(0x00); OWCRC(0x00, &crc); if (crc != OWReadByte()) { printf_P(PSTR("CRC mismatch on command & address\r\n")); return; } crc = 0; for (buf[0] = 0; buf[0] < 128; buf[0]++) { buf[1] = OWReadByte(); if (buf[0] > 0) { if (buf[0] % 16 != 0) printf_P(PSTR(" ")); else printf_P(PSTR("\r\n")); } printf_P(PSTR("%02x"), buf[1]); OWCRC(buf[1], &crc); } printf_P(PSTR("\r\n")); if (crc != OWReadByte()) { printf_P(PSTR("CRC mismatch on data\r\n")); return; } } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'c') { if (cmd.len < 5) { printf_P(PSTR("No arguments\r\n")); return; } arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); if (arg == 0) { printf_P(PSTR("Unparseable command\r\n")); return; } if (i == 5) { OWSendCmd(NULL, arg); return; } if (i < 29) { printf_P(PSTR("Can't parse ROM ID\r\n")); return; } for (i = 0; i < 8; i++) ROM[i] = (int)strtol((char *)cmd.buf + 6 + (3 * i), (char **)NULL, 16); OWSendCmd(ROM, arg); } else if (cmd.buf[0] == 't' && cmd.buf[1] == 'e') { if (cmd.len < 26) { printf_P(PSTR("Unable to parse ROM ID\r\n")); return; } for (i = 0; i < 8; i++) ROM[i] = (int)strtol((char *)cmd.buf + 3 * (i + 1), (char **)NULL, 16); if (ROM[0] != OW_FAMILY_TEMP) { printf_P(PSTR("ROM specified isn't a temperature sensor\r\n")); return; } OWSendCmd(ROM, OW_CONVERTT_CMD); i = 0; /* Wait for the conversion */ while (OWReadBit() == 0) i = 1; OWSendCmd(ROM, OW_RD_SCR_CMD); crc = 0; for (i = 0; i < 9; i++) { buf[i] = OWReadByte(); if (i < 8) OWCRC(buf[i], &crc); } if (crc != buf[8]) { printf_P(PSTR("CRC mismatch\r\n")); return; } /* 0 Temperature LSB * 1 Temperature MSB * 2 Th * 3 Tl * 4 Reserved * 5 Reserved * 6 Count Remain * 7 Count per C * 8 CRC */ #if 0 for (i = 0; i < 9; i++) printf_P(PSTR("%d\r\n"), buf[i]); #endif temp = buf[0]; if (buf[1] & 0x80) temp -= 256; temp >>= 1; tfrac = buf[7] - buf[6]; tfrac *= (uint16_t)100; tfrac /= buf[7]; tfrac += 75; if (tfrac < 100) { temp--; } else { tfrac -= 100; } printf_P(PSTR("%d.%02d\r\n"), temp, tfrac); } else if (cmd.buf[0] == 's' && cmd.buf[1] == 'r') { memset(ROM, 0, 8); i = OWFirst(ROM, 1, 0); do { switch (i) { case OW_BADWIRE: printf_P(PSTR("Presence pulse, but no module found, bad module/cabling?\r\n")); break; case OW_NOPRESENCE: printf_P(PSTR("No presence pulse found\r\n")); break; case OW_BADCRC: printf_P(PSTR("Bad CRC\r\n")); break; case OW_NOMODULES: case OW_FOUND: break; default: printf_P(PSTR("Unknown error from 1 wire library\r\n")); break; } if (i != OW_FOUND) break; for (i = 0; i < 8; i++) printf_P(PSTR("%02x%S"), ROM[i], i == 7 ? PSTR("\r\n") : PSTR(":")); i = OWNext(ROM, 1, 0); } while (1); } else if (cmd.buf[0] == 'i' && cmd.buf[1] == 'n') { switch (tolower(cmd.buf[3])) { case 'a': crc = PINA; break; case 'b': crc = PINB; break; case 'c': crc = PINC; break; case 'd': crc = PIND; break; default: printf_P(PSTR("Unknown port\r\n")); return; } printf_P(PSTR("0x%02x\r\n"), crc); } else if (cmd.buf[0] == 'o' && cmd.buf[1] == 'u') { crc = strtol((char *)cmd.buf + 8, (char **)NULL, 16); switch (tolower(cmd.buf[4])) { case 'a': PORTA = crc; break; case 'b': PORTB = crc; break; case 'c': PORTC = crc; break; case 'd': PORTD = crc; break; default: printf_P(PSTR("Unknown port\r\n")); return; } printf_P(PSTR("PORT%c <= 0x%02x\r\n"), toupper(cmd.buf[4]), crc); } else if (cmd.buf[0] == 'd' && cmd.buf[1] == 'd') { crc = strtol((char *)cmd.buf + 8, (char **)NULL, 16); switch (tolower(cmd.buf[4])) { case 'a': DDRA = crc; break; case 'b': DDRB = crc; break; case 'c': DDRC = crc; break; case 'd': DDRD = crc; break; default: printf_P(PSTR("Unknown port\r\n")); return; } printf_P(PSTR("0x%02x\r\n"), crc); } else if (cmd.buf[0] == 't' && cmd.buf[1] == 'c') { tempctrl_cmd((char *)cmd.buf); #ifdef WITHUSB } else if (cmd.buf[0] == 'u' && cmd.buf[1] == 's') { usb_gendata(); #endif } else { badcmd: printf_P(PSTR("Unknown command, ? for a list\r\n")); } }