Mercurial > ~darius > hgwebdir.cgi > tempctrl
view testavr.c @ 32:b0cb873c0206
Isolate the bus frobbing parts and the delays into a separate header.
This means the user only has to edit a single file to suit their
situation and allows the code to work with active drive systems as
well as passive pullups (ie 1 vs 2 IO pins)
author | darius |
---|---|
date | Sun, 23 Apr 2006 22:57:16 +0930 |
parents | 48056516b3eb |
children | 25fa387ef7e9 |
line wrap: on
line source
/* * Test various AVR bits and pieces * * $Id$ * * Copyright (c) 2004 * 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 <string.h> #include <ctype.h> #include <stdlib.h> #include <util/delay.h> #include "1wire.h" #include "usb.h" #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) #define UART_BAUD_RATE 38400 void process_cmd(void); void uart_putsP(const char *addr); void uart_puts(const char *addr); int uart_putc(char c); void uart_puts_dec(uint8_t a, uint8_t l); void uart_puts_hex(uint8_t a); char uart_getc(void); /* Receive buffer storage */ volatile struct { char buf[40]; uint8_t state; uint8_t len; } cmd = { .state = 255, .len = 0 }; /* Rx complete */ ISR(USART_RXC_vect) { volatile char pit; char c; while (UCSRA & _BV(RXC)) { /* 255 means we're waiting for main to process the command, just throw stuff away */ if (cmd.state == 255) { pit = UDR; continue; } c = UDR; /* End of line? */ if (c == '\n' || c == '\r') { cmd.buf[cmd.state + 1] = '\0'; uart_putsP(PSTR("\n\r")); cmd.len = cmd.state; cmd.state = 255; continue; } /* Backspace/delete */ if (c == 0x08 || c == 0x7f) { if (cmd.state > 0) { cmd.state--; uart_putsP(PSTR("\010\040\010")); } continue; } /* Anything unprintable just ignore it */ if (!isprint(c)) continue; cmd.buf[cmd.state] = tolower(c); /* Echo back to the user */ uart_putc(cmd.buf[cmd.state]); cmd.state++; /* Over flow? */ if (cmd.state == ((sizeof(cmd.buf) / sizeof(cmd.buf[0])) - 1)) { uart_putsP(PSTR("\n\rLine too long")); cmd.state = 0; continue; } } } /* Tx complete */ ISR(USART_TXC_vect) { } int main(void) { /* Disable interrupts while we frob stuff */ cli(); /* Disable JTAG (yes twice) */ MCUCSR |= _BV(JTD); MCUCSR |= _BV(JTD); /* USB data bus (7:0) */ DDRA = 0x00; PORTA = 0x00; /* USB control (3:0) */ DDRB = 0x0e; PORTB = 0x00; /* GPIO (0:7) */ DDRC = 0xff; PORTC = 0x00; /* GPIO (2:7) */ DDRD = 0xfc; PORTD = 0xfc; /* Init UART */ UBRRH = UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU) >> 8; UBRRL = (uint8_t)UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU); /* Enable receiver and transmitter. Turn on transmit interrupts */ UCSRA = 0; UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); uart_putsP(PSTR("\n\r\n\r===============\n\r" "Inited!\n\r\n\r")); /* Ready to go! */ sei(); usb_init(); _delay_us(1000); uart_putsP(PSTR("> ")); cmd.state = 0; /* Wait for user input or an "interrupt" */ while (1) { if (cmd.state == 255) { process_cmd(); uart_putsP(PSTR("> ")); /* Allow new characters to be processed */ cmd.state = 0; } if (!(PINB & _BV(PB0))) usb_intr(); } } 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] == '?') { uart_putsP(PSTR("rs Reset and check for presence\n\r" "sr Search the bus for ROMs\n\r" "re Read a bit\n\r" "rb Read a byte\n\r" "wr bit Write a bit\n\r" "wb byte Write a byte (hex)\n\r" "wc cmd [ROMID] Write command\n\r" "te ROMID Read the temperature from a DS1820\n\r" "in port Read from a port\n\r" "out port val Write to a port\n\r" "ddr port [val] Read/write DDR for a port\n\r")); return; } i = strlen((char *)cmd.buf); if (cmd.len < 2) goto badcmd; if (cmd.buf[0] == 'r' && cmd.buf[1] == 's') { uart_putsP(PSTR("Resetting... ")); if (OWTouchReset() == 1) uart_putsP(PSTR("No presence pulse found\n\r")); else uart_putsP(PSTR("Presence pulse found\n\r")); } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'e') { if (OWReadBit()) uart_putsP(PSTR("Read a 1\n\r")); else uart_putsP(PSTR("Read a 0\n\r")); } else if (cmd.buf[0] == 'r' && cmd.buf[1] == 'b') { uart_putsP(PSTR("Read a 0x")); uart_puts_hex(OWReadByte()); uart_putsP(PSTR("\n\r")); } else if (cmd.buf[0] == 'w' && cmd.buf[1] == 'r') { arg = strtol((char *)cmd.buf + 3, (char **)NULL, 10); OWWriteBit(arg); uart_putsP(PSTR("Wrote a ")); if (arg) uart_putsP(PSTR("1\n\r")); else uart_putsP(PSTR("0\n\r")); } 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] == 'w' && cmd.buf[1] == 'c') { if (cmd.len < 5) { uart_putsP(PSTR("No arguments\n\r")); return; } arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); if (arg == 0) { uart_putsP(PSTR("Unparseable command\n\r")); return; } if (i == 5) { OWSendCmd(NULL, arg); return; } if (i < 29) { uart_putsP(PSTR("Can't parse ROM ID\n\r")); 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) { uart_putsP(PSTR("Unable to parse ROM ID\n\r")); 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) { uart_putsP(PSTR("ROM specified isn't a temperature sensor\n\r")); return; } OWSendCmd(ROM, OW_CONVERTT_CMD); i = 0; while (OWReadBit() == 0) { i++; } 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]) { uart_putsP(PSTR("CRC mismatch\n\r")); return; } #if 0 uart_putsP(PSTR("temperature ")); uart_puts_dec(temp >> 4, 0); uart_putsP(PSTR(".")); uart_puts_dec((temp << 12) / 6553, 0); uart_putsP(PSTR("\n\r")); #else /* 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++) { uart_puts_dec(buf[i], 0); uart_putsP(PSTR("\n\r")); } #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; } if (temp < 0){ uart_putc('-'); uart_puts_dec(-temp, 0); } else uart_puts_dec(temp, 0); uart_putsP(PSTR(".")); uart_puts_dec(tfrac, 1); uart_putsP(PSTR("\n\r")); #endif } 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: uart_putsP(PSTR("Presence pulse, but no module found, bad module/cabling?\n\r")); break; case OW_NOPRESENCE: uart_putsP(PSTR("No presence pulse found\n\r")); break; case OW_BADCRC: uart_putsP(PSTR("Bad CRC\n\r")); break; case OW_NOMODULES: case OW_FOUND: break; default: uart_putsP(PSTR("Unknown error from 1 wire library\n\r")); break; } if (i != OW_FOUND) break; for (i = 0; i < 7; i++) { uart_puts_hex(ROM[i]); uart_putc(':'); } uart_puts_hex(ROM[7]); uart_putsP(PSTR("\n\r")); 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: uart_putsP(PSTR("Unknown port\n\r")); return; } uart_putsP(PSTR("0x")); uart_puts_hex(crc); uart_putsP(PSTR("\n\r")); } 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: uart_putsP(PSTR("Unknown port\n\r")); return; } uart_putsP(PSTR("0x")); uart_puts_hex(crc); uart_putsP(PSTR("\n\r")); } else if (cmd.buf[0] == 'u' && cmd.buf[1] == 's') { usb_gendata(); } else { badcmd: uart_putsP(PSTR("Unknown command, ? for a list\n\r")); } } int uart_putc(char c) { loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return(0); } void uart_putsP(const char *addr) { char c; while ((c = pgm_read_byte_near(addr++))) uart_putc(c); } void uart_puts(const char *addr) { while (*addr) uart_putc(*addr++); } void uart_puts_dec(uint8_t a, uint8_t l) { char s[4]; if (l && a < 10) uart_putsP(PSTR("0")); uart_puts(utoa(a, s, 10)); } void uart_puts_hex(uint8_t a) { char s[3]; if (a < 0x10) uart_putc('0'); uart_puts(utoa(a, s, 16)); } char uart_getc(void) { while (!(UCSRA & _BV(RXC))) ; return (UDR); }