Mercurial > ~darius > hgwebdir.cgi > avr
changeset 24:2b0ed085b95b
- Change to 38400 baud.
- Change to ATMega32
- Use interrupt driven serial comms (for rx anyway)
- Reformat.
author | darius |
---|---|
date | Mon, 12 Dec 2005 23:37:16 +1030 |
parents | 845934a4e7fe |
children | a52bc6b9e305 |
files | 1wire.h Makefile testavr.c |
diffstat | 3 files changed, 361 insertions(+), 233 deletions(-) [+] |
line wrap: on
line diff
--- a/1wire.h Mon Dec 12 23:32:59 2005 +1030 +++ b/1wire.h Mon Dec 12 23:37:16 2005 +1030 @@ -40,11 +40,11 @@ void OWCRC(uint8_t x, uint8_t *crc); void OWSendCmd(uint8_t *ROM, uint8_t cmd); -#define OWIREOUTPORT PORTC -#define OWIREOUTPIN 0 +#define OWIREOUTPORT PORTD +#define OWIREOUTPIN 2 -#define OWIREINPORT PINC -#define OWIREDDR DDRC +#define OWIREINPORT PIND +#define OWIREDDR DDRD #define OWIREINPIN OWIREOUTPIN /* Return codes for OWFirst()/OWNext() */
--- a/Makefile Mon Dec 12 23:32:59 2005 +1030 +++ b/Makefile Mon Dec 12 23:37:16 2005 +1030 @@ -3,10 +3,11 @@ # PROG= testavr -SRCS= 1wire.c testavr.c +SRCS= 1wire.c testavr.c usb.c -MCU= at90s8515 -CFLAGS+=-Os -g -Wall -fno-inline-functions -fno-inline -CFLAGS+=-DXTAL_CPU=4000000 - +MCU= atmega32 +PART= m32 +CFLAGS+=-O2 -g -Wall -Wunreachable-code +CFLAGS+=-DF_CPU=16000000 +#CFLAGS+= -mcall-prologues -frename-registers -fstrict-aliasing -fnew-ra .include "Makefile.avr"
--- a/testavr.c Mon Dec 12 23:32:59 2005 +1030 +++ b/testavr.c Mon Dec 12 23:37:16 2005 +1030 @@ -34,233 +34,319 @@ #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 19200 +#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); -int uart_getc(void); void uart_puts_dec(uint8_t a, uint8_t l); void uart_puts_hex(uint8_t a); - -int -main(void) { - uint8_t ROM[8]; - char cmdbuf[40]; - int8_t i, arg; - uint8_t crc, buf[9];; - int8_t temp; - uint16_t tfrac; - - cli(); +char uart_getc(void); - DDRC = 0xfc; - PORTC = 0x00; - DDRA = 0xff; - - /* Init UART */ - UBRR = UART_BAUD_SELECT(UART_BAUD_RATE,XTAL_CPU); - - /* Enable receiver and transmitter. Turn on transmit interrupts */ - UCR = _BV(RXEN) | _BV(TXEN); - - uart_putsP(PSTR("\n\r\n\r===============\n\r" - "Inited!\n\r\n\r")); +/* Receive buffer storage */ +volatile struct { + char buf[40]; + uint8_t state; + uint8_t len; +} cmd = { + .state = 255, + .len = 0 +}; - while (1) { - uart_putsP(PSTR("> ")); - i = 0; - while (1) { - cmdbuf[i] = tolower(uart_getc()); - if (cmdbuf[i] == '\n' || cmdbuf[i] == '\r') - break; - - /* Backspace/Delete */ - if (cmdbuf[i] == 0x08) { - if (i > 0) { - uart_putsP(PSTR("\010\040\010")); - i--; - } - continue; +/* 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")); } - - /* Anything unprintable just ignore it */ - if (!isprint(cmdbuf[i])) - continue; - - uart_putc(cmdbuf[i]); - i++; - if (i == sizeof(cmdbuf)) { - uart_putsP(PSTR("\n\rLine too long")); - i = 0; - break; - } - } - cmdbuf[i + 1] = '\0'; - uart_putsP(PSTR("\n\r")); - if (i == 0) - continue; - - if (cmdbuf[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" - "le byte Set the LED port\n\r")); - continue; } - if (i < 2) - goto badcmd; + /* 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) { - if (cmdbuf[0] == 'r' && cmdbuf[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 (cmdbuf[0] == 'r' && cmdbuf[1] == 'e') { - if (OWReadBit()) - uart_putsP(PSTR("Read a 1\n\r")); - else - uart_putsP(PSTR("Read a 0\n\r")); - } else if (cmdbuf[0] == 'r' && cmdbuf[1] == 'b') { - uart_putsP(PSTR("Read a 0x")); - uart_puts_hex(OWReadByte()); - uart_putsP(PSTR("\n\r")); - } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'r') { - arg = strtol(cmdbuf + 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 (cmdbuf[0] == 'w' && cmdbuf[1] == 'b') { - arg = (int)strtol(cmdbuf + 3, (char **)NULL, 16); - OWWriteByte(arg); - } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'c') { - i = strlen(cmdbuf); - if (i < 5) { - uart_putsP(PSTR("No arguments\n\r")); - continue; - } - - arg = (int)strtol(cmdbuf + 3, (char **)NULL, 16); - if (arg == 0) { - uart_putsP(PSTR("Unparseable command\n\r")); - continue; - } +} + +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 = 0x00; + + /* 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; - if (i == 5) { - OWSendCmd(NULL, arg); - continue; - } + /* 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 (i < 29) { - uart_putsP(PSTR("Can't parse ROM ID\n\r")); - continue; - } - for (i = 0; i < 8; i++) - ROM[i] = (int)strtol(cmdbuf + 6 + (3 * i), (char **)NULL, 16); - - OWSendCmd(ROM, arg); - } else if (cmdbuf[0] == 't' && cmdbuf[1] == 'e') { - if (strlen(cmdbuf) < 26) { - uart_putsP(PSTR("Unable to parse ROM ID\n\r")); - continue; - } - - for (i = 0; i < 8; i++) - ROM[i] = (int)strtol(cmdbuf + 3 * (i + 1), (char **)NULL, 16); + 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 (ROM[0] != OW_FAMILY_TEMP) { - uart_putsP(PSTR("ROM specified isn't a temperature sensor\n\r")); - continue; - } + if (i == 5) { + OWSendCmd(NULL, arg); + 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 (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; + } - if (crc != buf[8]) { - uart_putsP(PSTR("CRC mismatch\n\r")); - continue; - } + 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")); + 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 - */ + /* 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")); - } + for (i = 0; i < 9; i++) { + uart_puts_dec(buf[i], 0); + uart_putsP(PSTR("\n\r")); + } #endif - temp = buf[0]; - if (buf[0] & 0x01) - temp -= 256; - temp >>= 1; + 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; - } + 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")); + 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 (cmdbuf[0] == 's' && cmdbuf[1] == 'r') { - memset(ROM, 0, 8); + } else if (cmd.buf[0] == 's' && cmd.buf[1] == 'r') { + memset(ROM, 0, 8); - i = OWFirst(ROM, 1, 0); - do { - switch (i) { + 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; @@ -280,41 +366,82 @@ default: uart_putsP(PSTR("Unknown error from 1 wire library\n\r")); break; - } + } - if (i != OW_FOUND) - 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")); + 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 (cmdbuf[0] == 'l' && cmdbuf[1] == 'e') { - crc = (uint8_t)strtol(cmdbuf + 3, (char **)NULL, 16); - PORTA = crc; -#if 1 - uart_putsP(PSTR("LEDs set to 0x")); - uart_puts_hex(crc); - uart_putsP(PSTR("\n\r")); -#endif - } else { - badcmd: - uart_putsP(PSTR("Unknown command, ? for a list\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")); } +} - return(0); -} - int uart_putc(char c) { - loop_until_bit_is_set(USR, UDRE); + loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return(0); @@ -353,9 +480,9 @@ uart_puts(utoa(a, s, 16)); } -int +char uart_getc(void) { - while (!USR & 0x80) + while (!(UCSRA & _BV(RXC))) ; return (UDR);