# HG changeset patch # User Daniel O'Connor # Date 1423979214 -37800 # Node ID 951277329ee657b12c8531b833e8f683eafb231c # Parent 1188042ddc2ff79368961c1909c3cc006d80f270 Use splitargv instead of rolling our own. Fix WDT tripping continuously on self reset (disable WDT on startup). Pretty up startup message. diff -r 1188042ddc2f -r 951277329ee6 Makefile --- 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 diff -r 1188042ddc2f -r 951277329ee6 sprink.c --- 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 #include +#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")); } } - diff -r 1188042ddc2f -r 951277329ee6 water.c --- 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 #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; diff -r 1188042ddc2f -r 951277329ee6 water.h --- 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 . 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);