diff main.c @ 72:13f8e6eb5c01

Create a new repo for temperature control to make hacking on other things easier. Rename main file, remove USB stuff & fix makefiles, etc..
author darius@Inchoate
date Wed, 21 Jan 2009 16:37:32 +1030
parents testavr.c@1ef17cd8af7a
children 56165caf744b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.c	Wed Jan 21 16:37:32 2009 +1030
@@ -0,0 +1,572 @@
+/*
+ * 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 <avr/wdt.h>
+
+#include "cons.h"
+#include "1wire.h"
+#ifdef WITHUSB
+#include "usb.h"
+#endif
+#include "tempctrl.h"
+#include "ds1307.h"
+
+/*
+ * Mirror of the MCUCSR register, taken early during startup.
+ */
+uint8_t mcucsr __attribute__((section(".noinit")));
+
+void		process_cmd(void);
+
+/*
+ * Read out and reset MCUCSR early during startup.
+ */
+void handle_mcucsr(void)
+    __attribute__((section(".init3")))
+    __attribute__((naked));
+void handle_mcucsr(void) {
+    wdt_disable();
+    mcucsr = MCUCSR;
+    MCUCSR = 0;
+}
+
+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;
+
+    DDRB = 0x00;
+    PORTB = 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;
+
+#ifndef WITHUSB
+    /* Beep
+     *
+     * Fpwm = Fclk / (N * 510)
+     *      = 16e6 / (8 * 510)
+     *      = 3921Hz
+     *
+     * Behind ifndef because PB3 is A0 on PDI chip
+     *
+     * Phase correct PWM, non-inverted output, divide by 8 */
+    TCCR0 = _BV(WGM00) | _BV(WGM11) | _BV(COM00) | _BV(COM01) | _BV(CS01);
+    OCR0 = 128;
+#endif
+
+    /* Set up the one wire stuff */
+    OWInit();
+
+    /* Setup IIC */
+    ds1307_init();
+    
+    /* Init UART */
+    cons_init();
+    
+    /* Init temperature control stuff */
+    tempctrl_init();
+
+    printf_P(PSTR("\r\n\r\n===============\r\n"
+		  "Inited!\r\n\r\n"));
+
+    if ((mcucsr & _BV(PORF)) == _BV(PORF))
+	printf_P(PSTR("Power on reset\r\n"));
+
+    if ((mcucsr & _BV(EXTRF)) == _BV(EXTRF))
+	printf_P(PSTR("External reset\r\n"));
+
+    if ((mcucsr & _BV(BORF)) == _BV(BORF))
+	printf_P(PSTR("Brown-out reset\r\n"));
+
+    if ((mcucsr & _BV(WDRF)) == _BV(WDRF))
+	printf_P(PSTR("Watchdog reset\r\n"));
+
+    if ((mcucsr & _BV(JTRF)) == _BV(JTRF))
+	printf_P(PSTR("JTAG reset\r\n"));
+
+    /* Ready to go! */
+    sei();
+
+    /*
+     * Enable the watchdog with the largest prescaler.  Will cause a
+     * watchdog reset after approximately 2 s @ Vcc = 5 V
+     *
+     * Gets reset in the loop below and in the tempctrl.c timer IRQ
+     */
+    wdt_enable(WDTO_2S);
+
+#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) {
+	wdt_reset();
+
+	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], crc, buf[9], temp;
+    int8_t	i, arg;
+    int16_t	t;
+
+    /* User just pressed enter */
+    if (cmd.len == 0)
+	return;
+	     
+    if (!strcasecmp_P((char *)cmd.buf, PSTR("?")) ||
+	!strcasecmp_P((char *)cmd.buf, PSTR("help"))) {
+        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"
+		      "ou port val      Write to a port (val in hex)\r\n"
+		      "dd port [val]    Read/write DDR for a port (val in hex)\r\n"
+		      "rt ROMID	        Read DS2502 status page\r\n"
+		      "we ROMID adr val Write data into a DS2502 PROM (adr & val in hex)\r\n"
+		      "rr ROMID         Read DS2502 PROM\r\n"
+		      "zz               Reset MCU\r\n"
+		      "gc               Get time of day\r\n"
+		      "sc time          Set time of day (time is YYYY/MM/DD HH:MM:SS)\r\n"
+#ifdef WITHUSB
+		      "us               Generate USB data\r\n"
+#endif
+		      "tc ...           Temperature control related (tc help for more)\r\n"));
+	
+	return;
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("zz"), 2)) {
+	cli();
+	wdt_enable(WDTO_15MS);
+	for (;;)
+	    ;
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rs"), 2)) {
+	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 (!strncasecmp_P((char *)cmd.buf, PSTR("re"), 2)) {
+	if (OWReadBit())
+	    printf_P(PSTR("Read a 1\r\n"));
+	else
+	    printf_P(PSTR("Read a 0\r\n"));
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rb"), 2)) {
+	printf_P(PSTR("Read a 0x%02x\r\n"), OWReadByte());
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wr"), 2)) {
+	arg = strtol((char *)cmd.buf + 3, (char **)NULL, 10);
+	OWWriteBit(arg);
+	printf_P(PSTR("Wrote a %c\r\n"), arg ? '1' : '0');
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wb"), 2)) {
+	arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); 
+	OWWriteByte(arg);
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rt"), 2)) {
+	if (sscanf_P((char *)cmd.buf, PSTR("rt %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), 
+		     &ROM[0], &ROM[1], &ROM[2], &ROM[3],
+		     &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) {
+	    printf_P(PSTR("Unable to parse ROM ID\r\n"));
+	    return;
+	}
+	
+	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 (!strncasecmp_P((char *)cmd.buf, PSTR("we"), 2)) {
+	uint8_t	adr, data;
+	
+	if (sscanf_P((char *)cmd.buf, PSTR("we %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhx %hhx"),
+		     &ROM[0], &ROM[1], &ROM[2], &ROM[3],
+		     &ROM[4], &ROM[5], &ROM[6], &ROM[7],
+		     &adr, &data) != 10) {
+	    printf_P(PSTR("Unable to parse ROM ID\r\n"));
+	    return;
+	}
+
+	if (ROM[0] != OW_FAMILY_ROM) {
+	    printf_P(PSTR("ID specified isn't a ROM\r\n"));
+	    return;
+	}
+
+	if (OWTouchReset() != 0) {
+	    printf_P(PSTR("No presence\r\n"));
+	    return;
+	}
+
+	printf_P(PSTR("OWProgROM returned %S\r\n"), OWProgROM_Status[OWProgROM(ROM, buf[0], 2, &buf[1], 0, 0)]);
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rr"), 2)) {
+	if (sscanf_P((char *)cmd.buf, PSTR("rr %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"),
+		     &ROM[0], &ROM[1], &ROM[2], &ROM[3],
+		     &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) {
+	    printf_P(PSTR("Unable to parse ROM ID\r\n"));
+	    return;
+	}
+
+	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 (!strncasecmp_P((char *)cmd.buf, PSTR("wc"), 2)) {
+	uint8_t c;
+	
+	i = sscanf_P((char *)cmd.buf, PSTR("wc %hhx %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"),
+		     &ROM[0], &ROM[1], &ROM[2], &ROM[3],
+		     &ROM[4], &ROM[5], &ROM[6], &ROM[7],
+		     &c);
+	
+	if (i != 1 && i != 9) {
+	    printf_P(PSTR("Incorrect usage\r\n"));
+	    return;
+	}
+	    
+	if (i == 1) {
+	    OWSendCmd(i == 1 ? NULL : ROM, c);
+	    return;
+	}
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("te"), 2)) {
+	if (sscanf_P((char *)cmd.buf, PSTR("te %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), 
+		     &ROM[0], &ROM[1], &ROM[2], &ROM[3],
+		     &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) {
+	    printf_P(PSTR("Unable to parse ROM ID\r\n"));
+	    return;
+	}
+
+	t = OWGetTemp(ROM);
+	switch (t) {
+	    case OW_TEMP_WRONG_FAM:
+		printf_P(PSTR("ROM specified isn't a temperature sensor\r\n"));
+		break;
+
+	    case OW_TEMP_CRC_ERR:
+		printf_P(PSTR("CRC mismatch\r\n"));
+		break;
+
+	    case OW_TEMP_NO_ROM:
+		printf_P(PSTR("No ROM found\r\n"));
+		break;
+
+	    default:
+		printf_P(PSTR("%d.%02d\r\n"), GETWHOLE(t), GETFRAC(t));
+		break;
+	}
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("sr"), 2)) {
+	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 (!strncasecmp_P((char *)cmd.buf, PSTR("in"), 2)) {
+	uint8_t inp;
+	    
+	switch (tolower(cmd.buf[3])) {
+	    case 'a':
+		inp = PINA;
+		break;
+		
+	    case 'b':
+		inp = PINB;
+		break;
+		
+	    case 'c':
+		inp = PINC;
+		break;
+		
+	    case 'd':
+		inp = PIND;
+		break;
+		
+	    default:
+		printf_P(PSTR("Unknown port\r\n"));
+		return;
+	}
+	printf_P(PSTR("0x%02x\r\n"), inp);
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("ou"), 2)) {
+	char port;
+	int val;
+	
+	if (sscanf_P((char *)cmd.buf, PSTR("ou %c %x"), &port, &val) != 2) {
+	    printf_P(PSTR("Unable to parse ou arguments\r\n"));
+	    return;
+	}
+	
+	switch (port) {
+	    case 'a':
+		PORTA = val & 0xff;
+		break;
+		
+	    case 'b':
+		PORTB = val & 0xff;
+		break;
+		
+	    case 'c':
+		PORTC = val & 0xff;
+		break;
+		
+	    case 'd':
+		PORTD = val & 0xff;
+		break;
+		
+	    default:
+		printf_P(PSTR("Unknown port\r\n"));
+		return;
+	}
+	printf_P(PSTR("PORT%c <= 0x%02x\r\n"), toupper(port), val);
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("dd"), 2)) {
+	char port;
+	uint8_t val;
+	int num;
+	
+	num = sscanf_P((char *)cmd.buf, PSTR("dd %c %x"), &port, &val);
+	
+	if (num != 2 && num != 3) {
+	    printf_P(PSTR("Unable to parse dd arguments\r\n"));
+	    return;
+	}
+	
+	if (num == 2) {
+	    switch (port) {
+		case 'a':
+		    val = DDRA;
+		    break;
+
+		case 'b':
+		    val = DDRB;
+		    break;
+
+		case 'c':
+		    val = DDRC;
+		    break;
+		    
+		case 'd':
+		    val = DDRD;
+		    break;
+		
+		default:
+		    printf_P(PSTR("Unknown port\r\n"));
+		    return;
+	    }
+	    printf_P(PSTR("DDR%c => 0x%02x\r\n"), toupper(port), val);
+	} else {
+	    switch (port) {
+		case 'a':
+		    DDRA = val & 0xff;
+		    break;
+		
+		case 'b':
+		    DDRB = val & 0xff;
+		    break;
+		
+		case 'c':
+		    DDRC = val & 0xff;
+		    break;
+		
+		case 'd':
+		    DDRD = val & 0xff;
+		    break;
+		
+		default:
+		    printf_P(PSTR("Unknown port\r\n"));
+		    return;
+	    }
+	    printf_P(PSTR("DDR%c <= 0x%02x\r\n"), toupper(port), val);
+	}
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("tc"), 2)) {
+	tempctrl_cmd((char *)cmd.buf);
+#ifdef WITHUSB
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("us"), 2)) {
+	usb_gendata();
+#endif
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("gc"), 2)) {
+	ds1307_printtime(PSTR(""), PSTR("\r\n"));
+    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("sc"), 2)) {
+	if (cmd.len < 17) {
+	    printf_P(PSTR("Command not long enough\r\n"));
+	} else {
+	    if (ds1307_settod((char *)cmd.buf + 3) != 1)
+		printf_P(PSTR("Unable to set time of day\r\n"));
+	}
+    } else {
+	printf_P(PSTR("Unknown command, help for a list\r\n"));
+    }
+}
+