# HG changeset patch # User Daniel O'Connor # Date 1353984652 -37800 # Node ID 03592ca4d37e32b7641dd73c7ff77cea14d86e31 # Parent 435c6330896c41d36d1456d2eedc30f2a77689d7 Port tempctrl.c from AVR. I removed the beep code as I don't have a beeper on the STM32 board. Reworked the heat/cool stuff so it can use separate ports. diff -r 435c6330896c -r 03592ca4d37e BSDmakefile --- a/BSDmakefile Tue Nov 27 13:19:11 2012 +1030 +++ b/BSDmakefile Tue Nov 27 13:20:52 2012 +1030 @@ -13,6 +13,7 @@ startup_stm32f10x_md_mthomas.c \ syscalls.c \ system_stm32f10x.c \ + tempctrl.c \ touch.c STM32LIBS= usart gpio rcc rtc pwr bkp fsmc spi tim i2c crc diff -r 435c6330896c -r 03592ca4d37e flash.c --- a/flash.c Tue Nov 27 13:19:11 2012 +1030 +++ b/flash.c Tue Nov 27 13:20:52 2012 +1030 @@ -25,78 +25,11 @@ #define RW_IDLE 0 #define RW_RUNNING 1 -/* Holds all the settings needed */ -typedef struct { - uint8_t fermenter_ROM[8]; - uint8_t fridge_ROM[8]; - uint8_t ambient_ROM[8]; - int16_t target_temp; - uint16_t hysteresis; - /* How much to under/overshoot on heating/cooling */ - int16_t minheatovershoot; - int16_t mincoolovershoot; - - /* Minimum time the cooler can be on/off */ - int16_t mincoolontime; - int16_t mincoolofftime; - - /* Minimum time the heater can be on/off */ - int16_t minheatontime; - int16_t minheatofftime; - -#define TC_MODE_AUTO 'a' /* Automatic control */ -#define TC_MODE_HEAT 'h' /* Force heating */ -#define TC_MODE_COOL 'c' /* Force cooling */ -#define TC_MODE_IDLE 'i' /* Force idle */ -#define TC_MODE_NOTHING 'n' /* Do nothing (like idle but log nothing) */ - char mode; - - /* Bit patterns for various modes */ - uint8_t coolbits; - uint8_t heatbits; - uint8_t idlebits; - - /* Check/stale times */ - int16_t check_interval; - int16_t stale_factor; - - /* Beep if stale */ - int8_t dobeep; - - /* Pad to 4 bytes */ - uint8_t pad[1]; - -} __attribute__((packed, aligned(4))) settings_t; - -const settings_t default_settings = { - .fermenter_ROM = { 0x10, 0x4c, 0x7d, 0x53, 0x01, 0x08, 0x00, 0xff }, - .fridge_ROM = { 0x10, 0x6f, 0x40, 0x53, 0x01, 0x08, 0x00, 0x16 }, - .ambient_ROM = { 0x10, 0x76, 0x05, 0x53, 0x01, 0x08, 0x00, 0x8c }, - .target_temp = 1000, - .hysteresis = 100, - .minheatovershoot = 50, - .mincoolovershoot = -50, - .mincoolontime = 300, - .mincoolofftime = 600, - .minheatontime = 60, - .minheatofftime = 60, - .mode = TC_MODE_AUTO, - .coolbits = 1 << 6, - .heatbits = 1<< 7, - .idlebits = 0x00, - .check_interval = 10, - .stale_factor = 3, - .dobeep = 0 -}; - -/* RAM copy of setting */ -static settings_t ram_settings; - static int writestate = RW_IDLE; static int readstate = RW_IDLE; void -flashcmd(char **argv, int argc) { +flashcmd(int argc, char **argv) { uint8_t status, tmp, len; uint32_t addr; @@ -175,19 +108,6 @@ flashwriteword(data); } flashstopwrite(); - } else if (!strcmp(argv[0], "tw")) { - /* Copy default to RAM */ - bcopy(&default_settings, &ram_settings, sizeof(default_settings)); - - /* Write RAM copy into flash */ - flashwriteblock(0, sizeof(ram_settings), &ram_settings); - } else if (!strcmp(argv[0], "tr")) { - int crcok; - - /* Read flash copy to RAM */ - crcok = flashreadblock(0, sizeof(ram_settings), &ram_settings); - - printf("CRC is %s\r\n", crcok ? "OK" : "bad"); } else if (!strcmp(argv[0], "id")) { printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid()); } else { diff -r 435c6330896c -r 03592ca4d37e flash.h --- a/flash.h Tue Nov 27 13:19:11 2012 +1030 +++ b/flash.h Tue Nov 27 13:20:52 2012 +1030 @@ -1,4 +1,4 @@ -void flashcmd(char **, int); +void flashcmd(int argc, char **argv); uint16_t flashreadid(void); uint8_t flashreadstatus(void); void flashwritestatus(uint8_t status); diff -r 435c6330896c -r 03592ca4d37e hw.c --- a/hw.c Tue Nov 27 13:19:11 2012 +1030 +++ b/hw.c Tue Nov 27 13:20:52 2012 +1030 @@ -276,13 +276,13 @@ TIM_SelectOnePulseMode(TIM6, TIM_OPMode_Single); TIM_UpdateDisableConfig(TIM6, DISABLE); - /* Setup GPIO for delay test & 1-wire - * PE2 -> pin 3 on header - * PE3 -> pin 4 on header */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_Init(GPIOE, &GPIO_InitStructure); + /* Setup GPIO for delay test (2) 1-wire (3) & temp ctrl (4/5) + * PE2 -> 3 (on header) + * PE3 -> 4 + * PE4 -> 5 + * PE5 -> 6 + */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; OWInit(); diff -r 435c6330896c -r 03592ca4d37e main.c --- a/main.c Tue Nov 27 13:19:11 2012 +1030 +++ b/main.c Tue Nov 27 13:20:52 2012 +1030 @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -17,6 +18,8 @@ #include "hw.h" #include "lcd.h" #include "main.h" +#include "rtc.h" +#include "tempctrl.h" #include "touch.h" #define MAXARGS 10 @@ -151,11 +154,15 @@ lcd_ellipse(160, 120, 50, 30, 1, LCD_WHITE); lcd_ellipse(160, 120, 30, 50, 1, LCD_WHITE); + /* Setup temperature control stuff */ + tempctrl_init(); + while (1) { fputs("> ", stdout); - while (cmd.state != 255) - ; + while (cmd.state != 255) { + tempctrl_update(); + } if (cmd.len < 1) goto out; @@ -196,7 +203,9 @@ printf("X = %5d Y = %5d Z1 = %5d Z2 = %5d T = %7.2f T2 = %7.2f\r\n", x, y, z1, z2, t, t2); } } else if (!strcmp("fl", argv[0])) { - flashcmd(argv + 1, argc - 1); + flashcmd(argc - 1, argv + 1); + } else if (!strcmp("tc", argv[0])) { + tempctrl_cmd(argc - 1, argv + 1); } else if (!strcmp("pwm", argv[0])) { lcd_setpwm(atoi(argv[1])); } else if (!strcmp("timing", argv[0])) { @@ -324,6 +333,20 @@ printf("%hd.%02hd\r\n", GETWHOLE(res), GETFRAC(res)); break; } + } else if (!strcmp("rtc", argv[0])) { + float f, err, maxerr; + uint32_t d, i; + + maxerr = 0; + for (i = 0; i < 32768; i++) { + d = RTC_PS2USEC(32768 - i); + f = ((float)i * 1e6) / (float)RTC_PRESCALE; + err = fabs(d - f); + //rtcprintf("i = %d, d = %d, f = %.3f, err = %.3f\r\n", i, d, f, err); + if (err > maxerr) + maxerr = err; + } + printf("Max err = %.3f\r\n", maxerr); } else if (!strcmp("assert", argv[0])) { assert(0 == 1); } else if (!strcmp("zz", argv[0])) { diff -r 435c6330896c -r 03592ca4d37e tempctrl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tempctrl.c Tue Nov 27 13:20:52 2012 +1030 @@ -0,0 +1,528 @@ +/* + * Temperature control logic, copied from AVR version + * + * Copyright (c) 2012 + * Daniel O'Connor . 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 +#include +#include +#include +#include +#include +#include +#include "stm32f10x.h" + +#include "1wire.h" +#include "flash.h" +#include "tempctrl.h" + +/* Holds all the settings needed */ +typedef struct { + uint8_t fermenter_ROM[8]; + uint8_t fridge_ROM[8]; + uint8_t ambient_ROM[8]; + int16_t target_temp; + uint16_t hysteresis; + /* How much to under/overshoot on heating/cooling */ + int16_t minheatovershoot; + int16_t mincoolovershoot; + + /* Minimum time the cooler can be on/off */ + int16_t mincoolontime; + int16_t mincoolofftime; + + /* Minimum time the heater can be on/off */ + int16_t minheatontime; + int16_t minheatofftime; + +#define TC_MODE_AUTO 'a' /* Automatic control */ +#define TC_MODE_HEAT 'h' /* Force heating */ +#define TC_MODE_COOL 'c' /* Force cooling */ +#define TC_MODE_IDLE 'i' /* Force idle */ +#define TC_MODE_NOTHING 'n' /* Do nothing (like idle but log nothing) */ + char mode; + + /* GPIO port the heater & cooler are on */ + GPIO_TypeDef *coolport; + uint16_t coolpin; + + GPIO_TypeDef *heatport; + uint16_t heatpin; + + /* Check/stale times */ + int16_t check_interval; + int16_t stale_factor; + + uint8_t pad[3]; /* Pad to multiple of 4 bytes */ +} settings_t; + +/* Current settings in RAM */ +static settings_t settings; + +/* Defaults that are shoved into SPI flash if it isn't inited */ +const settings_t default_settings = { + .fermenter_ROM = { 0x10, 0x4c, 0x7d, 0x53, 0x01, 0x08, 0x00, 0xff }, + .fridge_ROM = { 0x10, 0x6d, 0x40, 0x53, 0x01, 0x08, 0x00, 0x16 }, + .ambient_ROM = { 0x10, 0x76, 0x05, 0x53, 0x01, 0x08, 0x00, 0x8e }, + .target_temp = 1000, + .hysteresis = 100, + .minheatovershoot = 50, + .mincoolovershoot = -50, + .mincoolontime = 300, + .mincoolofftime = 600, + .minheatontime = 60, + .minheatofftime = 60, + .mode = TC_MODE_AUTO, + .coolport = GPIOE, + .coolpin = GPIO_Pin_4, + .heatport = GPIOE, + .heatpin = GPIO_Pin_5, + .check_interval = 10, + .stale_factor = 3, +}; + +/* Local variable declarations */ + +/* Local function prototypes */ +static void tempctrl_load_or_init_settings(void); +static void tempctrl_default_settings(void); +static void tempctrl_write_settings(void); +static void setstate(char state); +static const char * state2long(char s); +static void printtemp(const char *name, int tmp, const char *trailer); + +/* + * tempctrl_init + * + */ +void +tempctrl_init(void) { + tempctrl_load_or_init_settings(); +} + +/* + * tempctrl_update + * + * Should be called in a normal context, could run things that take a long time. + * (ie 1wire bus stuff) + * + */ +void +tempctrl_update(void) { + /* State variables */ + static int32_t checktime = 0; // Time of next check + static int32_t lastdata = INT32_MIN; // Last time we got data + + static int16_t fermenter_temp = 0; // Fermenter temperature + static int16_t fridge_temp = 0; // Fridge temperature + static int16_t ambient_temp = 0; // Ambient temperature + static int32_t lastheaton = INT32_MIN; // Last time the heater was on + static int32_t lastheatoff = INT32_MIN;// Last time the heater was off + static int32_t lastcoolon = INT32_MIN; // Last time the cooler was on + static int32_t lastcooloff = INT32_MIN;// Last time the cooler was off + static char currstate = 'i'; // Current state + /* We init to times to INT32_MIN so that things function properly when + * now < settings.minheat/cool/on/offtime */ + + /* Temporary variables */ + int32_t tempt; + int16_t diff; + char nextstate; + int forced; + int stale; + time_t t; + struct tm tm; + char buf[23]; + + t = time(NULL); + + /* Time to check temperatures? */ + if (t < checktime) + return; + + checktime = t + settings.check_interval; + + /* Don't do any logging, just force idle and leave */ + if (settings.mode == TC_MODE_NOTHING) { + nextstate = 'i'; + goto setstate; + } + + /* Update our temperatures + * Can take a while (800ms each!) + */ + tempt = OWGetTemp(settings.fermenter_ROM); + fridge_temp = OWGetTemp(settings.fridge_ROM); + ambient_temp = OWGetTemp(settings.ambient_ROM); + + /* We only care about this one, only update the value we decide on + * only if it is valid + */ + if (tempt > OW_TEMP_BADVAL) { + fermenter_temp = tempt; + lastdata = t; + } + + /* Check for stale data */ + if (lastdata + (settings.check_interval * settings.stale_factor) < t) + stale = 1; + else + stale = 0; + + /* Default to remaining as we are */ + nextstate = '-'; + + /* Temperature diff, -ve => too cold, +ve => too warm */ + diff = fermenter_temp - settings.target_temp; + + switch (currstate) { + case 'i': + /* If we're idle then only heat or cool if the temperate difference is out of the + * hysteresis band + */ + if (abs(diff) > settings.hysteresis) { + if (diff < 0 && settings.minheatofftime + lastheatoff < t) + nextstate = 'h'; + else if (diff > 0 && settings.mincoolofftime + lastcooloff < t) + nextstate = 'c'; + } + break; + + case 'c': + /* Work out if we should go idle (based on min on time & overshoot) */ + if (diff + settings.mincoolovershoot < 0 && + settings.mincoolontime + lastcoolon < t) + nextstate = 'i'; + break; + + case 'h': + if (diff - settings.minheatovershoot > 0 && + settings.minheatontime + lastheaton < t) + nextstate = 'i'; + break; + + default: + printf("\r\nUnknown state %c, going to idle\n", currstate); + nextstate = 'i'; + break; + } + + /* Override if we have stale data */ + if (stale) + nextstate = 'i'; + + /* Handle state forcing */ + if (settings.mode != TC_MODE_AUTO) + forced = 1; + else + forced = 0; + + if (settings.mode == TC_MODE_IDLE) + nextstate = 'i'; + else if (settings.mode == TC_MODE_HEAT) + nextstate = 'h'; + else if (settings.mode == TC_MODE_COOL) + nextstate = 'c'; + + // Keep track of when we last turned things on or off + switch (nextstate) { + case 'c': + if (currstate == 'h') + lastheatoff = t; + lastcoolon = t; + break; + + case 'h': + if (currstate == 'c') + lastcooloff = t; + lastheaton = t; + break; + + default: + if (currstate == 'c') + lastcooloff = t; + if (currstate == 'h') + lastheatoff = t; + } + + if (nextstate != '-') + currstate = nextstate; + + + gmtime_r(&t, &tm); + assert(strftime(buf, sizeof(buf) - 1, "%Y/%m/%d %H:%M:%S: ", &tm) != 0); + fputs(buf, stdout); + printtemp("Tr", settings.target_temp, ", "); + printtemp("Fm", tempt, ", "); // Use actual value from sensor + printtemp("Fr", fridge_temp, ", "); + printtemp("Am", ambient_temp, ", "); + printf("St: %s, Fl: %s%s\r\n", state2long(currstate), + forced ? "F" : "", + stale ? "S" : ""); + + setstate: + setstate(currstate); +} + +/* + * Print out temperature (or short error code) with specified trailer + */ +static void +printtemp(const char *name, int tmp, const char *trailer) { + if (tmp > OW_TEMP_BADVAL) + printf("%s: %d.%02d%s", name, GETWHOLE(tmp), GETFRAC(tmp), trailer); + else + printf("%s: %s%s", name, OWTempStatusStr(tmp, 1), trailer); +} + +/* Read the settings from SPI flash + * If the CRC fails then reload from onboard flash + */ +static void +tempctrl_load_or_init_settings(void) { + /* XXX: todo */ + if (!flashreadblock(0, sizeof(settings), &settings)) { + fputs("CRC fails, loading defaults\r\n", stdout); + tempctrl_default_settings(); + tempctrl_write_settings(); + } +} + +/* Load in the defaults from flash */ +static void +tempctrl_default_settings(void) { + memcpy(&settings, &default_settings, sizeof(settings_t)); +} + +/* Write the current settings out to SPI flash */ +static void +tempctrl_write_settings(void) { + flashwriteblock(0, sizeof(settings), &settings); +} + +/* Set the relays to match the desired state */ +static void +setstate(char state) { + switch (state) { + case 'c': + GPIO_ResetBits(settings.heatport, settings.heatpin); + GPIO_SetBits(settings.coolport, settings.coolpin); + break; + + case 'h': + GPIO_ResetBits(settings.coolport, settings.coolpin); + GPIO_SetBits(settings.heatport, settings.heatpin); + break; + + default: + printf("Unknown state %c, setting idle\r\n", state); + /* fallthrough */ + + case 'i': + GPIO_ResetBits(settings.coolport, settings.coolpin); + GPIO_ResetBits(settings.heatport, settings.heatpin); + break; + } +} + +/* Handle user command + * + */ +void +tempctrl_cmd(int argc, char **argv) { + int16_t data; + uint8_t ROM[8]; + + if (argc < 1) { + printf("Unable to parse tc subcommand\r\n"); + return; + } + + if (!strcasecmp(argv[0], "help")) { + printf("tc help This help\r\n" + "tc save Save settings to EEPROM\r\n" + "tc load Load or default settings from EEPROM\r\n" + "tc dflt Load defaults from flash\r\n" + "tc list List current settings\r\n" + "tc mode [achin] Change control mode, must be one of\r\n" + " a Auto\r\n" + " c Always cool\r\n" + " h Always heat\r\n" + " i Always idle\r\n" + " n Like idle but don't log anything\r\n" + "tc X Y Set X to Y where X is one of\r\n" + " targ Target temperature\r\n" + " hys Hysteresis range\r\n" + " mhov Minimum heat overshoot\r\n" + " mcov Minimum cool overshoot\r\n" + " mcon Minimum cool on time\r\n" + " mcoff Minimum cool off time\r\n" + " mhin Minimum heat on time\r\n" + " mhoff Minimum heat off time\r\n" + "tc A B Set temperature sensor ID\r\n" + " Where A is ferm, frg or amb\r\n" + " and B is of the form xx:xx:xx:xx:xx:xx:xx:xx\r\n" + "\r\n" + " Times are in seconds\r\n" + " Temperatures are in hundredths of degrees Celcius\r\n" + ); + return; + } + + if (!strcasecmp(argv[0], "save")) { + tempctrl_write_settings(); + return; + } + if (!strcasecmp(argv[0], "load")) { + tempctrl_load_or_init_settings(); + return; + } + if (!strcasecmp(argv[0], "dflt")) { + tempctrl_default_settings(); + return; + } + if (!strcasecmp(argv[0], "list")) { + printf("Fermenter ROM ID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n" + "Fridge ROM ID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n" + "Ambient ROM ID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n" + "Mode - %c, Target - %d, Hystersis - %d\r\n" + "Min heat overshoot - %d, Min cool overshoot - %d\r\n" + "Min cool on time - %d, Min cool off time - %d\r\n" + "Min heat on time - %d, Min heat off time - %d\r\n", + settings.fermenter_ROM[0], settings.fermenter_ROM[1], settings.fermenter_ROM[2], settings.fermenter_ROM[3], + settings.fermenter_ROM[4], settings.fermenter_ROM[5], settings.fermenter_ROM[6], settings.fermenter_ROM[7], + settings.fridge_ROM[0], settings.fridge_ROM[1], settings.fridge_ROM[2], settings.fridge_ROM[3], + settings.fridge_ROM[4], settings.fridge_ROM[5], settings.fridge_ROM[6], settings.fridge_ROM[7], + settings.ambient_ROM[0], settings.ambient_ROM[1], settings.ambient_ROM[2], settings.ambient_ROM[3], + settings.ambient_ROM[4], settings.ambient_ROM[5], settings.ambient_ROM[6], settings.ambient_ROM[7], + settings.mode, settings.target_temp, settings.hysteresis, + settings.minheatovershoot, settings.mincoolovershoot, + settings.mincoolontime, settings.minheatontime, + settings.minheatontime, settings.minheatofftime + ); + return; + } + if (!strcasecmp(argv[0], "mode")) { + if (argc < 2) { + fputs("Incorrect number of arguments\r\n", stdout); + return; + } + + switch (argv[1][0]) { + case TC_MODE_AUTO: + case TC_MODE_HEAT: + case TC_MODE_COOL: + case TC_MODE_IDLE: + case TC_MODE_NOTHING: + settings.mode = argv[1][0]; + break; + + default: + printf("Unknown mode character '%c'\r\n", argv[1][0]); + break; + } + return; + } + if (!strcasecmp(argv[0], "ferm") || + !strcasecmp(argv[0], "frg") || + !strcasecmp(argv[0], "amb")) { + if (argc < 2) { + fputs("Incorrect number of arguments\r\n", stdout); + return; + } + + if (sscanf(argv[1], "%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("Unable to parse ROM ID\r\n"); + } else { + if (!strcasecmp(argv[0], "ferm")) + memcpy(&settings.fermenter_ROM, ROM, sizeof(ROM)); + if (!strcasecmp(argv[0], "frg")) + memcpy(&settings.fridge_ROM, ROM, sizeof(ROM)); + if (!strcasecmp(argv[0], "amb")) + memcpy(&settings.ambient_ROM, ROM, sizeof(ROM)); + } + return; + } + + /* Handle setting the multitude of variables + * It's last to simplify things */ + if (argc < 3) { + fputs("Incorrect number of arguments for variable/value\r\n", stdout); + return; + } + + if (sscanf(argv[2], "%hd", &data) != 1) { + printf("Unable to parse value for variable\r\n"); + return; + } + + if (!strcasecmp(argv[1], "targ")) { + settings.target_temp = data; + } else if (!strcasecmp(argv[1], "hys")) { + settings.hysteresis = data; + } else if (!strcasecmp(argv[1], "mhov")) { + settings.minheatovershoot = data; + } else if (!strcasecmp(argv[1], "mcov")) { + settings.mincoolovershoot = data; + } else if (!strcasecmp(argv[1], "mcon")) { + settings.mincoolontime = data; + } else if (!strcasecmp(argv[1], "mcoff")) { + settings.mincoolofftime = data; + } else if (!strcasecmp(argv[1], "mhon")) { + settings.minheatontime = data; + } else if (!strcasecmp(argv[1], "mhoff")) { + settings.minheatofftime = data; + } else { + printf("Unknown setting\r\n"); + } +} + +static const char* +state2long(char s) { + switch (s) { + case 'i': + return "idle"; + break; + + case 'c': + return "cool"; + break; + + case 'h': + return "heat"; + break; + + case '-': + return "-"; + break; + + default: + return "unknown"; + break; + } +} diff -r 435c6330896c -r 03592ca4d37e tempctrl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tempctrl.h Tue Nov 27 13:20:52 2012 +1030 @@ -0,0 +1,32 @@ +/* + * Temperature control headers + * + * Copyright (c) 2008 + * Daniel O'Connor . 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. + */ + +void tempctrl_init(void); +void tempctrl_update(void); +void tempctrl_cmd(int argc, char **argv); +int32_t gettod(void);