changeset 5:951277329ee6

Use splitargv instead of rolling our own. Fix WDT tripping continuously on self reset (disable WDT on startup). Pretty up startup message.
author Daniel O'Connor <darius@dons.net.au>
date Sun, 15 Feb 2015 16:16:54 +1030
parents 1188042ddc2f
children 7b9a1affcc94
files Makefile sprink.c water.c water.h
diffstat 4 files changed, 115 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Jan 27 23:40:50 2015 +1030
+++ b/Makefile	Sun Feb 15 16:16:54 2015 +1030
@@ -1,5 +1,5 @@
 PROG=	sprink
-SRCS=	sprink.c cons.c ds1307.c 1wire.c water.c
+SRCS=	sprink.c cons.c ds1307.c 1wire.c water.c splitargv.c
 
 #TPREFIX=	/usr/local/CrossPack-AVR/bin/
 
@@ -20,6 +20,7 @@
 
 #CFLAGS+=-DOW_DEBUG
 
+CFLAGS+=-Werror
 # Use minimal printf
 #LDFLAGS+=-Wl,-u,vfprintf -lprintf_min 
 
--- a/sprink.c	Tue Jan 27 23:40:50 2015 +1030
+++ b/sprink.c	Sun Feb 15 16:16:54 2015 +1030
@@ -36,12 +36,15 @@
 #include <util/delay.h>
 #include <avr/wdt.h>
 
+#include "1wire.h"
 #include "bitstring.h"
 #include "cons.h"
 #include "ds1307.h"
-#include "1wire.h"
+#include "splitargv.h"
 #include "water.h"
 
+#define MAXARGS 10
+
 /*
 ** Fuse bits should be set as follows
 **
@@ -90,18 +93,20 @@
     /* Disable interrupts while we frob stuff */
     cli();
 
+    /* Disable watchdog in case it was previously on */
+    wdt_disable();
+
     /* Init UART */
     cons_init();
-    
+
+    printf_P(PSTR("\r\n\r\n===============\r\n"));
+
     /* Init TWI etc */
     ds1307_init();
 
     /* Set up the one wire stuff */
     OWInit();
-    
-    /* Init water control state machine */
-    water_init();
-    
+
     /* Analogue input is PA0:7 */
     DDRA = 0x00;
     PORTA = 0x00;
@@ -111,7 +116,7 @@
 				 * datasheet says this is already 0 at
 				 * power on.. */
 #endif
-    
+
     /* PB0   Used for 1-wire bus
      * PB4:7 Used for relay board */
     DDRB = 0xf0;
@@ -125,9 +130,7 @@
     DDRD = 0x03;
     PORTD = 0x03;
 
-    printf_P(PSTR("\r\n\r\n===============\r\n"
-		  "Inited!\r\n\r\n"));
-
+    fputs_P(PSTR("Reset cause: "), stdout);
     if ((mcucsr & _BV(PORF)) == _BV(PORF))
 	printf_P(PSTR("Power on\r\n"));
 
@@ -148,23 +151,24 @@
     /* Ready to go! */
     sei();
 
+    /* Init water control state machine */
+    water_init();
+
     /*
      * 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);
 
     printf_P(PSTR("> "));
     cmd.state = 0;
-    
+
     /* Wait for user input or an "interrupt" */
     while (1) {
 	wdt_reset();
 
 	water_update();
-	
+
 	if (cmd.state == 255) {
 	    process_cmd();
 	    printf_P(PSTR("> "));
@@ -176,12 +180,21 @@
 
 void
 process_cmd(void) {
+    int argc;
+    char *argv[MAXARGS];
+
     /* User just pressed enter */
     if (cmd.len == 0)
 	return;
-	     
-    if (!strcasecmp_P((char *)cmd.buf, PSTR("?")) ||
-	!strcasecmp_P((char *)cmd.buf, PSTR("help"))) {
+
+    /* Split buffer into argv/argc (and de-volatilise) */
+    splitargv((char *)cmd.buf, 0, argv, MAXARGS, &argc);
+
+    if (argc == 0)
+	return;
+
+    if (!strcasecmp_P(argv[0], PSTR("?")) ||
+	!strcasecmp_P(argv[0], PSTR("help"))) {
         puts_P(PSTR("help               This help\r\n"
 		    "wa all dly time    Water all regions for time minutes after dly minutes\r\n"
 		    "gc                 Get time of day\r\n"
@@ -199,47 +212,20 @@
 		    "wc byte            Write byte to 1-wire bus\r\n"
 		    "zz                 Reset micro\r\n"));
 	return;
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wa"), 2)) {
-	water_cmd((char *)cmd.buf);
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("gc"), 2)) {
-	ds1307_printnow(PSTR(""), PSTR("\r\n"));
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("sc"), 2)) {
-	if (cmd.len < 17) {
-	    printf_P(PSTR("Invalid TOD\r\n"));
-	} else {
-	    if (ds1307_settod((char *)cmd.buf + 3) != 1)
-		printf_P(PSTR("Unable to set TOD\r\n"));
-	}
-    } 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("PORT %c <= 0x%02x\r\n"), toupper(cmd.buf[3]), inp);
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("an"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("wa"))) {
+	water_cmd(argc - 1, argv + 1);
+    } else if (!strcasecmp_P(argv[0], PSTR("an"))) {
 	uint16_t	res;
 	int		pin;
-	
-	if (sscanf_P((char *)cmd.buf, PSTR("an %d"), &pin) != 1) {
+	char		*eptr;
+
+	if (argc != 2) {
+	    printf_P(PSTR("Bad usage\r\n"));
+	    return;
+	}
+
+	pin = strtol(argv[1], &eptr, 0);
+	if (eptr == argv[1]) {
 	    printf_P(PSTR("Unable to parse\r\n"));
 	    return;
 	}
@@ -250,7 +236,7 @@
 
 	/* Select desired pin, use AVREF */
 	ADMUX = _BV(pin);
-	
+
 	/* Enable ADC, start conversion, set divisor to 64
 	 * (8e6 / 64 => 125kHz (max is 200kHz)
 	 */
@@ -264,51 +250,54 @@
 
 	/* Disable ADC */
 	ADCSRA = 0;
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("ou"), 2)) {
-	char port;
+    } else if (!strcasecmp_P(argv[0], PSTR("ou"))) {
 	int val;
-	
-	if (sscanf_P((char *)cmd.buf, PSTR("ou %c %x"), &port, &val) != 2) {
-	    printf_P(PSTR("Unable to parse\r\n"));
+	char *eptr;
+
+	if (argc != 3) {
+	    printf_P(PSTR("Bad usage\r\n"));
 	    return;
 	}
-	
-	switch (port) {
+
+	val = strtol(argv[2], &eptr, 0);
+	if (eptr == argv[2]) {
+	    printf_P(PSTR("Unable to parse val\r\n"));
+	    return;
+	}
+
+	switch (argv[1][0]) {
 	    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;
+	printf_P(PSTR("PORT%c <= 0x%02x\r\n"), toupper(argv[1][0]), val);
+    } else if (!strcasecmp_P(argv[0], PSTR("dd"))) {
 	uint8_t val;
-	int num;
-	
-	num = sscanf_P((char *)cmd.buf, PSTR("dd %c %x"), &port, &val);
-	
-	if (num != 1 && num != 2) {
-	    printf_P(PSTR("Unable to parse dd arguments\r\n"));
+	char *eptr;
+
+	if (argc != 2 && argc != 3) {
+	    printf_P(PSTR("Bad usage\r\n"));
 	    return;
 	}
-	
-	if (num == 1) {
-	    switch (port) {
+
+	if (argc == 1) {
+	    switch (argv[1][0]) {
 		case 'a':
 		    DDRA = val;
 		    break;
@@ -320,79 +309,80 @@
 		case 'c':
 		    DDRC = val;
 		    break;
-		    
+
 		case 'd':
 		    DDRD = val;
 		    break;
-		
+
 		default:
 		    printf_P(PSTR("Unknown port\r\n"));
 		    return;
 	    }
-	    printf_P(PSTR("DDR%c => 0x%02x\r\n"), toupper(port), val);
+	    printf_P(PSTR("DDR%c => 0x%02x\r\n"), toupper(argv[1][0]), val);
 	} else {
-	    switch (port) {
+	    val = strtol(argv[2], &eptr, 0);
+	    if (eptr == argv[2]) {
+		printf_P(PSTR("Unable to parse val\r\n"));
+		return;
+	    }
+
+	    switch (argv[1][0]) {
 		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);
+	    printf_P(PSTR("DDR%c <= 0x%02x\r\n"), toupper(argv[1][0]), val);
 	}
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("zz"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("zz"))) {
 	cli();
 	wdt_enable(WDTO_15MS);
 	for (;;)
 	    ;
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("sr"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("sr"))) {
 	uint8_t	ROM[8];
 	int8_t	i;
-	
-	memset(ROM, 0, 8);
 
 	i = OWFirst(ROM, 1, 0);
 	do {
 	    switch (i) {
 		case OW_NOMODULES:
+		    return;
+
 		case OW_FOUND:
+		    for (i = 0; i < 8; i++)
+			printf_P(PSTR("%02x%S"), ROM[i], i == 7 ? PSTR("\r\n") : PSTR(":"));
 		    break;
-		    
+
 		case OW_BADWIRE:
 		case OW_NOPRESENCE:
 		case OW_BADCRC:
 		default:
 		    printf_P(PSTR("Err %d\r\n"), i);
-		    break;
+		    return;
 	    }
-		
-	    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("te"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("te"))) {
 	uint8_t	ROM[8];
 	int16_t	t;
-	
-	if (sscanf_P((char *)cmd.buf, PSTR("te %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), 
+
+	if (sscanf_P(argv[1], PSTR("%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"));
@@ -417,26 +407,28 @@
 		printf_P(PSTR("%d.%02d\r\n"), GETWHOLE(t), GETFRAC(t));
 		break;
 	}
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("re"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("re"))) {
 	printf_P(PSTR("Reset = %d\r\n"), OWTouchReset());
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rb"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("rb"))) {
 	printf_P(PSTR("Read %d\r\n"), OWReadBit());
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rc"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("rc"))) {
 	printf_P(PSTR("Read 0x%02x\r\n"), OWReadByte());
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wb"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("wb"))) {
 	uint8_t	d;
-	
+
 	if (sscanf_P((char *)cmd.buf, PSTR("wb %hhu"), &d) != 1) {
 	    printf_P(PSTR("Can't parse bit\r\n"));
 	    return;
 	}
 	OWWriteBit(d);
 	printf_P(PSTR("Wrote %d\r\n"), d);
-    } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wc"), 2)) {
+    } else if (!strcasecmp_P(argv[0], PSTR("wc"))) {
 	uint8_t	d;
-	
-	if (sscanf_P((char *)cmd.buf, PSTR("wc %hhx"), &d) != 1) {
-	    printf_P(PSTR("Can't parse byte\r\n"));
+	char *eptr;
+
+	d = strtol(argv[1], &eptr, 16);
+	if (eptr == argv[1]) {
+	    printf_P(PSTR("Unable to parse byte\r\n"));
 	    return;
 	}
 
@@ -446,4 +438,3 @@
 	printf_P(PSTR("Unknown command, help for a list\r\n"));
     }
 }
-
--- a/water.c	Tue Jan 27 23:40:50 2015 +1030
+++ b/water.c	Sun Feb 15 16:16:54 2015 +1030
@@ -36,6 +36,7 @@
 #include <util/crc16.h>
 
 #include "ds1307.h"
+#include "splitargv.h"
 #include "water.h"
 
 struct tm {
@@ -123,37 +124,16 @@
     }
 }
 
-#define MAXARGS 10
-
 /* Parse water related command */
 void
-water_cmd(char *buf) {
-    char	*e, **btmp;
+water_cmd(int argc, char **argv) {
+    char	*e;
     uint16_t	delay;
     uint16_t	time;
     long	tmp;
-    int		i, argc, skip;
-    char	*argv[MAXARGS];
+    int		i;
 
-    /* Split command string on space/tab boundaries into argv/argc */
-    argc = 0;
-    btmp = &buf;
-    skip = 1;
-    while (1) {
-	    argv[argc] = strsep(btmp, " \t");
-	    if (argv[argc] == '\0')
-		    break;
-	    /* Skip first arg (ie 'wa') */
-	    if (skip) {
-		    skip = 0;
-		    continue;
-	    }
-	    argc++;
-	    if (argc == MAXARGS)
-		    break;
-    }
-
-    if (!strcmp(argv[0], "all")) {
+    if (!strcmp_P(argv[0], PSTR("all"))) {
 	    if (argc != 3) {
 		    puts_P(PSTR("Wrong number of arguments, usage: wa all delay time\r\n"));
 		    return;
--- a/water.h	Tue Jan 27 23:40:50 2015 +1030
+++ b/water.h	Sun Feb 15 16:16:54 2015 +1030
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012
+ * Copyright (c) 2015
  *      Daniel O'Connor <darius@dons.net.au>.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,6 +25,6 @@
  */
 
 void		water_init(void);
-void		water_cmd(char *buf);
+void		water_cmd(int argc, char **argv);
 void		water_update(void);