changeset 206:82603c0ded37

forgot text
author Matt Johnston <matt@ucc.asn.au>
date Sun, 30 Mar 2014 20:35:30 +0800
parents 2023bd995276 (diff) ff1b772da5d0 (current diff)
children ea800fcc1ad4
files
diffstat 27 files changed, 2720 insertions(+), 2700 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-# Name: Makefile
-# Author: <insert your name here>
-# Copyright: <insert your copyright message here>
-# License: <insert your license reference here>
-
-# This is a prototype Makefile. Modify it according to your needs.
-# You should at least check the settings for
-# DEVICE ....... The AVR device you compile for
-# CLOCK ........ Target AVR clock rate in Hertz
-# OBJECTS ...... The object files created from your source files. This list is
-#                usually the same as the list of source files with suffix ".o".
-# PROGRAMMER ... Options to avrdude which define the hardware you use for
-#                uploading to the AVR and the interface where this hardware
-#                is connected. We recommend that you leave it undefined and
-#                add settings like this to your ~/.avrduderc file:
-#                   default_programmer = "stk500v2"
-#                   default_serial = "avrdoper"
-# FUSES ........ Parameters for avrdude to flash the fuses appropriately.
-
-DEVICE     = atmega328
-PROGDEVICE     = atmega328p
-CLOCK      = 2000000
-PROGRAMMER = #-c stk500v2 -P avrdoper
-PROGRAMMER = -c stk500 -P ~/dev/stk500 -p $(PROGDEVICE)  -B 2
-SOURCE_1WIRE = onewire.c simple_ds18b20.c crc8.c
-SOURCE    = main.c
-SOURCE += $(SOURCE_1WIRE)
-LIBS       = -lm
-
-# default but 2mhz
-FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0x62:m
-
-# ATMega8 fuse bits used above (fuse bits for other devices are different!):
-# Example for 8 MHz internal oscillator
-# Fuse high byte:
-# 0xd9 = 1 1 0 1   1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
-#        ^ ^ ^ ^   ^ ^ ^------ BOOTSZ0
-#        | | | |   | +-------- BOOTSZ1
-#        | | | |   +---------- EESAVE (set to 0 to preserve EEPROM over chip erase)
-#        | | | +-------------- WDTON
-#        | | +---------------- SPIEN (if set to 1, serial programming is disabled)
-#        | +------------------ DWEN
-#        +-------------------- RSTDISBL (if set to 0, RESET pin is disabled)
-# Fuse low byte:
-# 0x62 = 0 1 1 0   0 0 1 0
-#        ^ ^ \ /   \--+--/
-#        | |  |       +------- CKSEL 3..0 (8M internal RC)
-#        | |  +--------------- SUT 1..0 (slowly rising power)
-#        | +------------------ CKOUT
-#        +-------------------- CLKDIV8
-#
-# For computing fuse byte values for other devices and options see
-# the fuse bit calculator at http://www.engbedded.com/fusecalc/
-
-
-# Tune the lines below only if you know what you are doing:
-
-AVRDUDE = avrdude $(PROGRAMMER) 
-COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 -mcall-prologues -fdata-sections -ffunction-sections  -Wl,--gc-sections -Wl,--relax --combine -fwhole-program  -Wl,-u,vfprintf -lprintf_flt -lm
-
-# symbolic targets:
-all:	main.hex
-
-.c.o:
-	$(COMPILE) -c $< -o $@
-
-.S.o:
-	$(COMPILE) -x assembler-with-cpp -c $< -o $@
-# "-x assembler-with-cpp" should not be necessary since this is the default
-# file type for the .S (with capital S) extension. However, upper case
-# characters are not always preserved on Windows. To ensure WinAVR
-# compatibility define the file type manually.
-
-.c.s:
-	$(COMPILE) -S $< -o $@
-
-flash:	all
-	$(AVRDUDE) -U flash:w:main.hex:i
-
-checkprog:	
-	$(AVRDUDE) -v 
-
-fuse:
-	$(AVRDUDE) $(FUSES)
-
-# Xcode uses the Makefile targets "", "clean" and "install"
-install: flash 
-
-# if you use a bootloader, change the command below appropriately:
-load: all
-	bootloadHID main.hex
-
-clean:
-	rm -f main.hex main.elf $(OBJECTS)
-
-# file targets:
-main.elf: $(SOURCE)
-	$(COMPILE) -o main.elf $(SOURCE) $(LIBS)
-
-main.hex: main.elf
-	rm -f main.hex
-	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
-	avr-size --format=avr --mcu=$(DEVICE) main.elf
-# If you have an EEPROM section, you must also create a hex file for the
-# EEPROM and add it to the "flash" target.
-
-# Targets for code debugging and analysis:
-disasm:	main.elf
-	avr-objdump -d main.elf
-
-cpp:
-	$(COMPILE) -E main.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,20 @@
+Wort fermentation control.
+
+py/ code runs on a raspberry pi with ds18b20 sensors.
+Dependencies can be installed with pip from requirements.txt
+
+---
+
+web/ code is a Bottle web app for showing graphs and also
+controlling the  temperature from a phone-optimised UI
+
+---
+
+old/ is the previous version that ran on an avr talking over a serial bluetooth device
+with a separate internet-connected router relaying to the web interface.
+
+
+Matt Johnston
[email protected]
+
+This code may be freely used, distributed, relicensed, and modified for any purpose.
--- a/crc8.c	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* please read copyright-notice at EOF */
-
-#include <stdint.h>
-
-#define CRC8INIT    0x00
-#define CRC8POLY    0x18              //0X18 = X^8+X^5+X^4+X^0
-
-uint8_t crc8( uint8_t *data, uint16_t number_of_bytes_in_data )
-{
-	uint8_t  crc;
-	uint16_t loop_count;
-	uint8_t  bit_counter;
-	uint8_t  b;
-	uint8_t  feedback_bit;
-	
-	crc = CRC8INIT;
-
-	for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++)
-	{
-		b = data[loop_count];
-		
-		bit_counter = 8;
-		do {
-			feedback_bit = (crc ^ b) & 0x01;
-	
-			if ( feedback_bit == 0x01 ) {
-				crc = crc ^ CRC8POLY;
-			}
-			crc = (crc >> 1) & 0x7F;
-			if ( feedback_bit == 0x01 ) {
-				crc = crc | 0x80;
-			}
-		
-			b = b >> 1;
-			bit_counter--;
-		
-		} while (bit_counter > 0);
-	}
-	
-	return crc;
-}
-
-/*
-This code is from Colin O'Flynn - Copyright (c) 2002 
-only minor changes by M.Thomas 9/2004
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
--- a/crc8.h	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-#ifndef CRC8_H_
-#define CRC8_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-uint8_t crc8( uint8_t* data, uint16_t number_of_bytes_in_data );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/*
-This is based on code from :
-
-Copyright (c) 2002 Colin O'Flynn
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
--- a/ds18x20.h	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-#ifndef DS18X20_H_
-#define DS18X20_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#include <stdint.h>
-
-// DS18x20 EERPROM support disabled(0) or enabled(1) :
-#define DS18X20_EEPROMSUPPORT     1
-// decicelsius functions disabled(0) or enabled(1):
-#define DS18X20_DECICELSIUS       1
-// max. resolution functions disabled(0) or enabled(1):
-#define DS18X20_MAX_RESOLUTION    1
-// extended output via UART disabled(0) or enabled(1) :
-#define DS18X20_VERBOSE           1
-
-
-/* return values */
-#define DS18X20_OK                0x00
-#define DS18X20_ERROR             0x01
-#define DS18X20_START_FAIL        0x02
-#define DS18X20_ERROR_CRC         0x03
-
-#define DS18X20_INVALID_DECICELSIUS  2000
-
-#define DS18X20_POWER_PARASITE    0x00
-#define DS18X20_POWER_EXTERN      0x01
-
-#define DS18X20_CONVERSION_DONE   0x00
-#define DS18X20_CONVERTING        0x01
-
-/* DS18X20 specific values (see datasheet) */
-#define DS18S20_FAMILY_CODE       0x10
-#define DS18B20_FAMILY_CODE       0x28
-#define DS1822_FAMILY_CODE        0x22
-
-#define DS18X20_CONVERT_T         0x44
-#define DS18X20_READ              0xBE
-#define DS18X20_WRITE             0x4E
-#define DS18X20_EE_WRITE          0x48
-#define DS18X20_EE_RECALL         0xB8
-#define DS18X20_READ_POWER_SUPPLY 0xB4
-
-#define DS18B20_CONF_REG          4
-#define DS18B20_9_BIT             0
-#define DS18B20_10_BIT            (1<<5)
-#define DS18B20_11_BIT            (1<<6)
-#define DS18B20_12_BIT            ((1<<6)|(1<<5))
-#define DS18B20_RES_MASK          ((1<<6)|(1<<5))
-
-// undefined bits in LSB if 18B20 != 12bit
-#define DS18B20_9_BIT_UNDF        ((1<<0)|(1<<1)|(1<<2))
-#define DS18B20_10_BIT_UNDF       ((1<<0)|(1<<1))
-#define DS18B20_11_BIT_UNDF       ((1<<0))
-#define DS18B20_12_BIT_UNDF       0
-
-// conversion times in milliseconds
-#define DS18B20_TCONV_12BIT       750
-#define DS18B20_TCONV_11BIT       DS18B20_TCONV_12_BIT/2
-#define DS18B20_TCONV_10BIT       DS18B20_TCONV_12_BIT/4
-#define DS18B20_TCONV_9BIT        DS18B20_TCONV_12_BIT/8
-#define DS18S20_TCONV             DS18B20_TCONV_12_BIT
-
-// constant to convert the fraction bits to cel*(10^-4)
-#define DS18X20_FRACCONV          625
-
-// scratchpad size in bytes
-#define DS18X20_SP_SIZE           9
-
-// DS18X20 EEPROM-Support
-#define DS18X20_WRITE_SCRATCHPAD  0x4E
-#define DS18X20_COPY_SCRATCHPAD   0x48
-#define DS18X20_RECALL_E2         0xB8
-#define DS18X20_COPYSP_DELAY      10 /* ms */
-#define DS18X20_TH_REG            2
-#define DS18X20_TL_REG            3
-
-#define DS18X20_DECIMAL_CHAR      '.'
-
-
-extern uint8_t DS18X20_find_sensor(uint8_t *diff, 
-	uint8_t id[]);
-extern uint8_t DS18X20_get_power_status(uint8_t id[]);
-extern uint8_t DS18X20_start_meas( uint8_t with_external,
-	uint8_t id[]);
-// returns 1 if conversion is in progress, 0 if finished
-// not available when parasite powered
-extern uint8_t DS18X20_conversion_in_progress(void);
-
-
-#if DS18X20_DECICELSIUS
-extern uint8_t DS18X20_read_decicelsius( uint8_t id[],
-	int16_t *decicelsius );
-extern uint8_t DS18X20_read_decicelsius_single( uint8_t familycode,
-	int16_t *decicelsius );
-extern uint8_t DS18X20_format_from_decicelsius( int16_t decicelsius, 
-	char s[], uint8_t n);
-#endif /* DS18X20_DECICELSIUS */
-
-
-#if DS18X20_MAX_RESOLUTION
-// temperature unit for max. resolution is �C * 10e-4
-// examples: -250625 -> -25.0625�C, 1250000 -> 125.0000 �C
-extern uint8_t DS18X20_read_maxres( uint8_t id[],
-	int32_t *temperaturevalue );
-extern uint8_t DS18X20_read_maxres_single( uint8_t familycode,
-	int32_t *temperaturevalue );
-extern uint8_t DS18X20_format_from_maxres( int32_t temperaturevalue, 
-	char s[], uint8_t n);
-#endif /* DS18X20_MAX_RESOLUTION */
-
-
-#if DS18X20_EEPROMSUPPORT
-// write th, tl and config-register to scratchpad (config ignored on DS18S20)
-uint8_t DS18X20_write_scratchpad( uint8_t id[], 
-	uint8_t th, uint8_t tl, uint8_t conf);
-// read scratchpad into array SP
-uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n);
-// copy values int scratchpad into DS18x20 eeprom
-uint8_t DS18X20_scratchpad_to_eeprom( uint8_t with_power_extern,
-	uint8_t id[] );
-// copy values from DS18x20 eeprom into scratchpad
-uint8_t DS18X20_eeprom_to_scratchpad( uint8_t id[] );
-#endif /* DS18X20_EEPROMSUPPORT */
-
-
-#if DS18X20_VERBOSE
-extern void DS18X20_show_id_uart( uint8_t *id, size_t n );
-extern uint8_t DS18X20_read_meas_all_verbose( void );
-#endif /* DS18X20_VERBOSE */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
--- a/main.c	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1200 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/sleep.h>
-#include <util/delay.h>
-#include <avr/pgmspace.h>
-#include <avr/eeprom.h>
-#include <avr/wdt.h>
-#include <util/atomic.h>
-#include <util/crc16.h>
-
-#include "simple_ds18b20.h"
-#include "onewire.h"
-
-// configuration params
-// - measurement interval
-// - transmit interval
-// - bluetooth params
-// - number of sensors (and range?)
-
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
-// TICK should be 8 or less (8 untested). all timers need
-// to be a multiple.
-
-#define TICK 6
-// we have 1024 prescaler, 32768 crystal.
-#define SLEEP_COMPARE (32*TICK-1)
-
-#define VALUE_NOSENSOR 0x07D0 // 125 degrees
-#define VALUE_BROKEN 0x07D1 // 125.0625
-
-#define OVERSHOOT_MAX_DIV 1800.0 // 30 mins
-#define WORT_INVALID_TIME 900 // 15 mins
-// fridge min/max are only used if the wort sensor is invalid
-#define FRIDGE_AIR_MIN_RANGE 40 // 4º
-#define FRIDGE_AIR_MAX_RANGE 40 // 4º
-
-#define BAUD 19200
-#define UBRR ((F_CPU)/8/(BAUD)-1)
-
-#define PORT_LED PORTC
-#define DDR_LED DDRC
-#define PIN_LED PC4
-
-#define PORT_SHDN PORTD
-#define DDR_SHDN DDRD
-#define PIN_SHDN PD7
-
-#define PORT_FRIDGE PORTD
-#define DDR_FRIDGE DDRD
-#define PIN_FRIDGE PD6
-
-// total amount of 16bit values available for measurements.
-// adjust emperically, be sure to allow enough stack space too
-#define TOTAL_MEASUREMENTS 800
-
-// each sensor slot uses 8 bytes
-#define MAX_SENSORS 6
-
-// fixed at 8, have a shorter name
-#define ID_LEN OW_ROMCODE_SIZE
-
-// #define HAVE_UART_ECHO
-
-// stores a value of clock_epoch combined with the remainder of TCNT2,
-// for 1/32 second accuracy
-struct epoch_ticks
-{
-    uint32_t ticks;
-    // remainder
-    uint8_t rem;
-};
-
-// eeprom-settable parameters. all timeouts should
-// be a multiple of TICK (6 seconds probably)
-static uint16_t measure_wake = 61; // not a divisor of comms_wake
-static uint16_t comms_wake = 600;
-static uint8_t wake_secs = 30;
-// decidegrees
-static int16_t fridge_setpoint = 180; // 18.0ºC
-static uint16_t fridge_difference = 3; // 0.3ºC
-static uint16_t fridge_delay = 600; // seconds
-
-static uint16_t overshoot_delay = 720; // 12 mins
-static uint8_t overshoot_factor = 10; // 1.0ºC
-
-// ---- Atomic guards required accessing these variables
-// clock_epoch in seconds
-static uint32_t clock_epoch;
-static uint16_t comms_count;
-static uint16_t measure_count;
-// ---- End atomic guards required
-
-static uint16_t n_measurements;
-
-// calculated at startup as TOTAL_MEASUREMENTS/n_sensors
-static uint16_t max_measurements;
-
-static uint16_t measurements[TOTAL_MEASUREMENTS];
-
-static struct epoch_ticks first_measurement_clock;
-// last_measurement_clock is redundant but checks that we're not missing
-// samples
-static struct epoch_ticks last_measurement_clock;
-static struct epoch_ticks last_comms_clock;
-
-// boolean flags
-static uint8_t need_measurement;
-static uint8_t need_comms;
-static uint8_t uart_enabled;
-static uint8_t stay_awake;
-static uint8_t button_pressed;
-
-// counts down from WAKE_SECS to 0, goes to deep sleep when hits 0
-static uint8_t comms_timeout;
-
-static uint8_t readpos;
-static char readbuf[30];
-static uint8_t have_cmd;
-
-static uint8_t n_sensors;
-static uint8_t sensor_id[MAX_SENSORS][ID_LEN];
-
-static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS;
-static int16_t last_wort = DS18X20_INVALID_DECICELSIUS;
-static struct epoch_ticks fridge_off_clock = {0};
-static struct epoch_ticks fridge_on_clock = {0};
-static struct epoch_ticks wort_valid_clock = {0};
-
-int uart_putchar(char c, FILE *stream);
-static void long_delay(int ms);
-static void blink();
-static uint16_t adc_vcc();
-
-static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
-        _FDEV_SETUP_WRITE);
-
-static uint16_t crc_out;
-static FILE _crc_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
-        _FDEV_SETUP_WRITE);
-// convenience
-static FILE *crc_stdout = &_crc_stdout;
-
-
-// thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/
-#define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size))
-#define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst))
-#define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size))
-#define eeprom_write(src, eeprom_field) { eeprom_write_from(&src, eeprom_field, sizeof(src)); }
-
-#define EXPECT_MAGIC 0x67c9
-
-struct __attribute__ ((__packed__)) __eeprom_data {
-    uint16_t measure_wake;
-    uint16_t comms_wake;
-    uint8_t wake_secs;
-
-    int16_t fridge_setpoint; // decidegrees
-    uint16_t fridge_difference; // decidegrees
-    uint16_t fridge_delay;
-
-    uint16_t overshoot_delay;
-    uint8_t overshoot_factor; // decidegrees
-
-#if 0
-    static uint8_t wort_id[ID_LEN];
-    static uint8_t fridge_id[ID_LEN];
-#endif
-
-    uint16_t magic;
-};
-
-static const uint8_t fridge_id[ID_LEN] = 
-    {0x28,0xCE,0xB2,0x1A,0x03,0x00,0x00,0x99};
-static const uint8_t wort_id[ID_LEN] = 
-    {0x28,0x49,0xBC,0x1A,0x03,0x00,0x00,0x54};
-
-static void deep_sleep();
-
-// 0 or 1
-static uint8_t
-is_fridge_on()
-{
-    if (PORT_FRIDGE & _BV(PIN_FRIDGE))
-    {
-        return 1;
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-// Very first setup
-static void
-setup_chip()
-{
-    cli();
-
-    // stop watchdog timer (might have been used to cause a reset)
-    wdt_reset();
-    MCUSR &= ~_BV(WDRF);
-    WDTCSR |= _BV(WDCE) | _BV(WDE);
-    WDTCSR = 0;
-
-    // Set clock to 2mhz
-    CLKPR = _BV(CLKPCE);
-    // divide by 4
-    CLKPR = _BV(CLKPS1);
-
-    // enable pullups
-    PORTB = 0xff; // XXX change when using SPI
-    PORTD = 0xff;
-    PORTC = 0xff;
-
-    // 3.3v power for bluetooth and SD
-    DDR_LED |= _BV(PIN_LED);
-    DDR_SHDN |= _BV(PIN_SHDN);
-
-    PORT_FRIDGE &= ~_BV(PIN_FRIDGE);
-    DDR_FRIDGE |= _BV(PIN_FRIDGE);
-
-    // set pullup
-    PORTD |= _BV(PD2);
-    // INT0 setup
-    EICRA = (1<<ISC01); // falling edge - data sheet says it won't work?
-    EIMSK = _BV(INT0);
-
-    // comparator disable
-    ACSR = _BV(ACD);
-
-    // disable adc pin input buffers
-    DIDR0 = 0x3F; // acd0-adc5
-    DIDR1 = (1<<AIN1D)|(1<<AIN0D); // ain0/ain1
-
-    sei();
-}
-
-static void
-set_aux_power(uint8_t on)
-{
-    if (on)
-    {
-        PORT_SHDN &= ~_BV(PIN_SHDN);
-    }
-    else
-    {
-        PORT_SHDN |= _BV(PIN_SHDN);
-    }
-}
-
-static void
-get_epoch_ticks(struct epoch_ticks *t)
-{
-    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-    {
-        t->ticks = clock_epoch;
-        t->rem = TCNT2;
-    }
-}
-
-static void 
-set_measurement(uint8_t sensor, uint16_t measurement, uint16_t reading)
-{
-    measurements[sensor*max_measurements + measurement] = reading;
-}
-
-static uint16_t 
-get_measurement(uint8_t sensor, uint16_t measurement)
-{
-    return measurements[sensor*max_measurements + measurement];
-}
-
-static void
-setup_tick_counter()
-{
-    // set up counter2. 
-    // COM21 COM20 Set OC2 on Compare Match (p116)
-    // WGM21 Clear counter on compare
-    //TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21);
-    // toggle on match
-    TCCR2A = _BV(COM2A0);
-    // CS22 CS21 CS20  clk/1024
-    TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
-    // set async mode
-    ASSR |= _BV(AS2);
-    TCNT2 = 0;
-    OCR2A = SLEEP_COMPARE;
-    // interrupt
-    TIMSK2 = _BV(OCIE2A);
-}
-
-static void 
-uart_on()
-{
-    // Power reduction register
-    PRR &= ~_BV(PRUSART0);
- 
-    // All of this needs to be done each time after turning off the PRR
-    // baud rate
-    UBRR0H = (unsigned char)(UBRR >> 8);
-    UBRR0L = (unsigned char)UBRR;
-    // set 2x clock, improves accuracy of UBRR
-    UCSR0A |= _BV(U2X0);
-    UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
-    //8N1
-    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
-    uart_enabled = 1;
-}
-
-static void 
-uart_off()
-{
-    // Turn off interrupts and disable tx/rx
-    UCSR0B = 0;
-    uart_enabled = 0;
-
-    // Power reduction register
-    PRR |= _BV(PRUSART0);
-}
-
-int 
-uart_putchar(char c, FILE *stream)
-{
-    if (!uart_enabled)
-    {
-        return EOF;
-    }
-    // XXX could perhaps sleep in the loop for power.
-    if (c == '\n')
-    {
-        loop_until_bit_is_set(UCSR0A, UDRE0);
-        UDR0 = '\r';
-    }
-    loop_until_bit_is_set(UCSR0A, UDRE0);
-    UDR0 = c;
-    if (stream == crc_stdout)
-    {
-        crc_out = _crc_ccitt_update(crc_out, c);
-    }
-    if (c == '\r')
-    {
-        loop_until_bit_is_set(UCSR0A, UDRE0);
-        UDR0 = '\n';
-        if (stream == crc_stdout)
-        {
-            crc_out = _crc_ccitt_update(crc_out, '\n');
-        }
-    }
-    return (unsigned char)c;
-}
-
-static void
-cmd_fetch()
-{
-    crc_out = 0;
-
-    fprintf_P(crc_stdout, PSTR("START\n"));
-    {
-        struct epoch_ticks now;
-        get_epoch_ticks(&now);
-        fprintf_P(crc_stdout, PSTR("now=%lu\n"), now.ticks);
-        fprintf_P(crc_stdout, PSTR("now_rem=%hhu\n"), now.rem);
-    }
-    fprintf_P(crc_stdout, PSTR("time_step=%hu\n"), measure_wake);
-    fprintf_P(crc_stdout, PSTR("first_time=%lu\n"), first_measurement_clock.ticks);
-    fprintf_P(crc_stdout, PSTR("first_time_rem=%hhu\n"), first_measurement_clock.rem);
-    fprintf_P(crc_stdout, PSTR("last_time=%lu\n"),  last_measurement_clock.ticks);
-    fprintf_P(crc_stdout, PSTR("last_time_rem=%hhu\n"),  last_measurement_clock.rem);
-    fprintf_P(crc_stdout, PSTR("comms_time=%lu\n"), last_comms_clock.ticks);
-    fprintf_P(crc_stdout, PSTR("comms_time_rem=%hhu\n"), last_comms_clock.rem);
-    fprintf_P(crc_stdout, PSTR("voltage=%hu\n"), adc_vcc());
-    fprintf_P(crc_stdout, PSTR("measure=%hu\n"), measure_wake);
-    fprintf_P(crc_stdout, PSTR("comms=%hu\n"), comms_wake);
-    fprintf_P(crc_stdout, PSTR("wake=%hhu\n"), wake_secs);
-    fprintf_P(crc_stdout, PSTR("fridge=%.1f\n"), fridge_setpoint/10.0);
-    fprintf_P(crc_stdout, PSTR("fridge_diff=%.1f\n"), fridge_difference/10.0);
-    fprintf_P(crc_stdout, PSTR("fridge_delay=%hu\n"), fridge_delay);
-    fprintf_P(crc_stdout, PSTR("overshoot_factor=%.1f\n"), overshoot_factor/10.0);
-    fprintf_P(crc_stdout, PSTR("overshoot_delay=%hu\n"), overshoot_delay);
-    fprintf_P(crc_stdout, PSTR("fridge_status=%hhu\n"), is_fridge_on());
-    fprintf_P(crc_stdout, PSTR("fridge_last_on=%lu\n"), fridge_on_clock.ticks);
-    fprintf_P(crc_stdout, PSTR("fridge_last_off=%lu\n"), fridge_off_clock.ticks);
-    fprintf_P(crc_stdout, PSTR("last_fridge=%hu\n"), last_fridge);
-    fprintf_P(crc_stdout, PSTR("last_wort=%hu\n"), last_wort);
-    fprintf_P(crc_stdout, PSTR("tick_secs=%d\n"), TICK);
-    fprintf_P(crc_stdout, PSTR("tick_wake=%d\n"), SLEEP_COMPARE);
-    fprintf_P(crc_stdout, PSTR("maxsens=%hhu\n"), MAX_SENSORS);
-    fprintf_P(crc_stdout, PSTR("totalmeas=%hu\n"), TOTAL_MEASUREMENTS);
-    fprintf_P(crc_stdout, PSTR("sensors=%hhu\n"), n_sensors);
-    for (uint8_t s = 0; s < n_sensors; s++)
-    {
-        fprintf_P(crc_stdout, PSTR("sensor_id%hhu="), s);
-        printhex(sensor_id[s], ID_LEN, crc_stdout);
-        fputc('\n', crc_stdout);
-    }
-    fprintf_P(crc_stdout, PSTR("measurements=%hu\n"), n_measurements);
-    for (uint16_t n = 0; n < n_measurements; n++)
-    {
-        fprintf_P(crc_stdout, PSTR("meas%hu="), n);
-        for (uint8_t s = 0; s < n_sensors; s++)
-        {
-            fprintf_P(crc_stdout, PSTR(" %04hx"), get_measurement(s, n));
-        }
-        fputc('\n', crc_stdout);
-    }
-    fprintf_P(crc_stdout, PSTR("END\n"));
-    fprintf_P(stdout, PSTR("CRC=%hu\n"), crc_out);
-}
-
-static void
-cmd_clear()
-{
-    n_measurements = 0;
-    printf_P(PSTR("cleared\n"));
-}
-
-static void
-cmd_btoff()
-{
-    uint8_t rem;
-    uint16_t count_copy;
-    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-    {
-        count_copy = comms_count;
-        rem = TCNT2;
-    }
-    printf_P(PSTR("next_wake=%hu,"), comms_wake-count_copy);
-    printf_P(PSTR("rem=%hhu,"), rem);
-    printf_P(PSTR("tick_secs=%hhu,"), TICK);
-    printf_P(PSTR("tick_wake=%hhu\n"), SLEEP_COMPARE);
-    _delay_ms(100);
-    comms_timeout = 0;
-    stay_awake = 0;
-}
-
-static void
-cmd_reset()
-{
-    printf_P(PSTR("reset\n"));
-    _delay_ms(100);
-    cli(); // disable interrupts 
-    wdt_enable(WDTO_15MS); // enable watchdog 
-    while(1); // wait for watchdog to reset processor 
-}
-
-static void
-cmd_measure()
-{
-    printf_P(PSTR("measuring\n"));
-    need_measurement = 1;
-}
-
-static void
-cmd_sensors()
-{
-    uint8_t ret = simple_ds18b20_start_meas(NULL);
-    printf_P(PSTR("All sensors, ret %hhu, waiting...\n"), ret);
-    long_delay(DS18B20_TCONV_12BIT);
-    simple_ds18b20_read_all();
-}
-
-static void
-init_sensors()
-{
-    uint8_t id[OW_ROMCODE_SIZE];
-    printf_P(PSTR("init sensors\n"));
-    ow_reset();
-    for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
-    {
-        diff = ow_rom_search( diff, &id[0] );
-        if( diff == OW_PRESENCE_ERR ) {
-            printf_P( PSTR("No Sensor found\r") );
-            return;
-        }
-        
-        if( diff == OW_DATA_ERR ) {
-            printf_P( PSTR("Bus Error\r") );
-            return;
-        }
-
-        if (n_sensors < MAX_SENSORS)
-        {
-            memcpy(sensor_id[n_sensors], id, ID_LEN);
-            printf_P(PSTR("Added sensor %hhu : "), n_sensors);
-            printhex(id, ID_LEN, stdout);
-            putchar('\n');
-            n_sensors++;
-        }
-        else
-        {
-            printf_P(PSTR("Too many sensors\n"));
-        }
-    }
-
-    max_measurements = TOTAL_MEASUREMENTS / n_sensors;
-}
-
-static void
-load_params()
-{
-    uint16_t magic;
-    eeprom_read(magic, magic);
-    if (magic == EXPECT_MAGIC)
-    {
-        eeprom_read(measure_wake, measure_wake);
-        eeprom_read(comms_wake, comms_wake);
-        eeprom_read(wake_secs, wake_secs);
-        eeprom_read(fridge_setpoint, fridge_setpoint);
-        eeprom_read(fridge_difference, fridge_difference);
-        eeprom_read(fridge_delay, fridge_delay);
-        eeprom_read(overshoot_delay, overshoot_delay);
-        eeprom_read(overshoot_factor, overshoot_factor);
-    }
-}
-
-static void
-cmd_get_params()
-{
-    printf_P(PSTR("measure %hu\n"), measure_wake);
-    printf_P(PSTR("comms %hu\n"), comms_wake);
-    printf_P(PSTR("wake %hhu\n"), wake_secs);
-    printf_P(PSTR("tick %d\n"), TICK);
-    printf_P(PSTR("fridge %.1fº\n"), fridge_setpoint / 10.0f);
-    printf_P(PSTR("fridge difference %.1fº\n"), fridge_difference / 10.0f);
-    printf_P(PSTR("fridge_delay %hu\n"), fridge_delay);
-    printf_P(PSTR("overshoot factor %.1fº\n"), overshoot_factor / 10.0f);
-    printf_P(PSTR("overshoot delay %hu\n"), overshoot_delay);
-    printf_P(PSTR("sensors %hhu (%hhu)\n"), 
-            n_sensors, MAX_SENSORS);
-    printf_P(PSTR("meas %hu (%hu)\n"),
-            max_measurements, TOTAL_MEASUREMENTS);
-}
-
-static void
-cmd_set_params(const char *params)
-{
-    uint16_t new_measure_wake;
-    uint16_t new_comms_wake;
-    uint8_t new_wake_secs;
-    int ret = sscanf_P(params, PSTR("%hu %hu %hhu"),
-            &new_measure_wake, &new_comms_wake, &new_wake_secs);
-
-    if (ret != 3)
-    {
-        printf_P(PSTR("Bad values\n"));
-    }
-    else
-    {
-        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-        {
-            eeprom_write(new_measure_wake, measure_wake);
-            eeprom_write(new_comms_wake, comms_wake);
-            eeprom_write(new_wake_secs, wake_secs);
-            uint16_t magic = EXPECT_MAGIC;
-            eeprom_write(magic, magic);
-        }
-        printf_P(PSTR("set_params for next boot\n"));
-        printf_P(PSTR("measure %hu comms %hu wake %hhu\n"),
-                new_measure_wake, new_comms_wake, new_wake_secs);
-    }
-}
-
-// returns true if eeprom was written
-static bool
-set_initial_eeprom()
-{
-    uint16_t magic;
-    eeprom_read(magic, magic);
-    if (magic == EXPECT_MAGIC)
-    {
-        return false;
-    }
-
-    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-    {
-        eeprom_write(measure_wake, measure_wake);
-        eeprom_write(comms_wake, comms_wake);
-        eeprom_write(wake_secs, wake_secs);
-        eeprom_write(fridge_setpoint, fridge_setpoint);
-        eeprom_write(fridge_difference, fridge_difference);
-        eeprom_write(fridge_delay, fridge_delay);
-        eeprom_write(overshoot_delay, overshoot_delay);
-        eeprom_write(overshoot_factor, overshoot_factor);
-        magic = EXPECT_MAGIC;
-        eeprom_write(magic, magic);
-    }
-
-    return true;
-}
-
-static void
-cmd_set_fridge_setpoint(char *params)
-{
-    float new_f = atof(params);
-    if (new_f < 2 || new_f > 30)
-    {
-        printf_P(PSTR("Bad fridge value %f\n"), new_f);
-        return;
-    }
-
-    int16_t old_setpoint = fridge_setpoint;
-
-    fridge_setpoint = new_f * 10;
-    bool written = set_initial_eeprom();
-    if (!written)
-    {
-        if (old_setpoint != fridge_setpoint)
-        {
-            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-            {
-                eeprom_write(fridge_setpoint, fridge_setpoint);
-            }
-        }
-    }
-    printf_P(PSTR("old fridge %.1fº new fridge %.1fº\n"), 
-            old_setpoint / 10.0f, fridge_setpoint / 10.0f);
-}
-
-static void
-cmd_set_fridge_difference(char *params)
-{
-    float new_f = atof(params);
-    if (new_f < 0 || new_f > 30)
-    {
-        printf_P(PSTR("Bad fridge value %f\n"), new_f);
-        return;
-    }
-
-    fridge_difference = new_f * 10;
-    bool written = set_initial_eeprom();
-    if (!written)
-    {
-        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-        {
-            eeprom_write(fridge_difference, fridge_difference);
-        }
-    }
-    printf_P(PSTR("new fridge difference %.1fº\n"), fridge_difference / 10.0f);
-}
-
-static void
-cmd_set_fridge_delay(char *params)
-{
-    uint16_t new_delay = atoi(params);
-    if (new_delay < 5)
-    {
-        printf_P(PSTR("Bad fridge delay %d\n"), new_delay);
-        return;
-    }
-
-    fridge_delay = new_delay;
-    bool written = set_initial_eeprom();
-    if (!written)
-    {
-        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-        {
-            eeprom_write(fridge_delay, fridge_delay);
-        }
-    }
-    printf_P(PSTR("new fridge delay %hu\n"), fridge_delay);
-}
-
-static void
-cmd_set_overshoot_factor(char *params)
-{
-    float new_f = atof(params);
-    if (new_f <= 0 || new_f > 20)
-    {
-        printf_P(PSTR("Bad overshoot factor %f\n"), new_f);
-        return;
-    }
-
-    uint8_t old = overshoot_factor;
-
-    overshoot_factor = new_f * 10;
-    bool written = set_initial_eeprom();
-    if (!written)
-    {
-        if (old != overshoot_factor)
-        {
-            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-            {
-                eeprom_write(overshoot_factor, overshoot_factor);
-            }
-        }
-    }
-    printf_P(PSTR("old factor %.1fº new factor %.1fº\n"), 
-            old / 10.0f, overshoot_factor / 10.0f);
-}
-    
-static void
-cmd_set_overshoot_delay(char *params)
-{
-    uint16_t new_delay = atoi(params);
-    if (new_delay < 5)
-    {
-        printf_P(PSTR("Bad overshoot delay %d\n"), new_delay);
-        return;
-    }
-
-    overshoot_delay = new_delay;
-    bool written = set_initial_eeprom();
-    if (!written)
-    {
-        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-        {
-            eeprom_write(overshoot_delay, overshoot_delay);
-        }
-    }
-    printf_P(PSTR("new overshoot delay %hu\n"), overshoot_delay);
-}
-
-static void
-cmd_awake()
-{
-    stay_awake = 1;
-    printf_P(PSTR("awake\n"));
-}
-
-static void
-read_handler()
-{
-    if (strcmp_P(readbuf, PSTR("fetch")) == 0)
-    {
-        cmd_fetch();
-    }
-    else if (strcmp_P(readbuf, PSTR("clear")) == 0)
-    {
-        cmd_clear();
-    }
-    else if (strcmp_P(readbuf, PSTR("btoff")) == 0)
-    {
-        cmd_btoff();
-    }
-    else if (strcmp_P(readbuf, PSTR("measure")) == 0)
-    {
-        cmd_measure();
-    }
-    else if (strcmp_P(readbuf, PSTR("sensors")) == 0)
-    {
-        cmd_sensors();
-    }
-    else if (strcmp_P(readbuf, PSTR("get_params")) == 0)
-    {
-        cmd_get_params();
-    }
-    else if (strncmp_P(readbuf, PSTR("set_params "), 11) == 0)
-    {
-        cmd_set_params(&readbuf[11]);
-    }
-    else if (strcmp_P(readbuf, PSTR("awake")) == 0)
-    {
-        cmd_awake();
-    }
-    else if (strncmp_P(readbuf, PSTR("fridge_setpoint "), 16) == 0)
-    {
-        cmd_set_fridge_setpoint(&readbuf[16]);
-    }
-    else if (strncmp_P(readbuf, PSTR("fridge_diff "), 12) == 0)
-    {
-        cmd_set_fridge_difference(&readbuf[12]);
-    }
-    else if (strncmp_P(readbuf, PSTR("fridge_delay "), 13) == 0)
-    {
-        cmd_set_fridge_delay(&readbuf[13]);
-    }
-    else if (strncmp_P(readbuf, PSTR("overshoot_delay "), 16) == 0)
-    {
-        cmd_set_overshoot_delay(&readbuf[16]);
-    }
-    else if (strncmp_P(readbuf, PSTR("overshoot_factor "), 17) == 0)
-    {
-        cmd_set_overshoot_factor(&readbuf[17]);
-    }
-    else if (strcmp_P(readbuf, PSTR("reset")) == 0)
-    {
-        cmd_reset();
-    }
-    else
-    {
-        printf_P(PSTR("Bad command '%s'\n"), readbuf);
-    }
-}
-
-ISR(INT0_vect)
-{
-    button_pressed = 1;
-    blink();
-    _delay_ms(100);
-    blink();
-}
-
-
-ISR(USART_RX_vect)
-{
-    char c = UDR0;
-#ifdef HAVE_UART_ECHO
-    uart_putchar(c, NULL);
-#endif
-    if (c == '\r' || c == '\n')
-    {
-        if (readpos > 0)
-        {
-            readbuf[readpos] = '\0';
-            have_cmd = 1;
-            readpos = 0;
-        }
-    }
-    else
-    {
-        readbuf[readpos] = c;
-        readpos++;
-        if (readpos >= sizeof(readbuf))
-        {
-            readpos = 0;
-        }
-    }
-}
-
-ISR(TIMER2_COMPA_vect)
-{
-    TCNT2 = 0;
-    measure_count += TICK;
-    comms_count += TICK;
-
-    clock_epoch += TICK;
-
-    if (comms_timeout != 0)
-    {
-        comms_timeout -= TICK;
-    }
-
-    if (measure_count >= measure_wake)
-    {
-        measure_count = 0;
-        need_measurement = 1;
-    }
-
-    if (comms_count >= comms_wake)
-    {
-        comms_count = 0;
-        need_comms = 1;
-    }
-}
-
-static void
-deep_sleep()
-{
-    // p119 of manual
-    OCR2A = SLEEP_COMPARE;
-    loop_until_bit_is_clear(ASSR, OCR2AUB);
-
-    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
-    sleep_mode();
-}
-
-static void
-idle_sleep()
-{
-    set_sleep_mode(SLEEP_MODE_IDLE);
-    sleep_mode();
-}
-
-static uint16_t
-adc_vcc()
-{
-    PRR &= ~_BV(PRADC);
-    
-    // /16 prescaler
-    ADCSRA = _BV(ADEN) | _BV(ADPS2);
-
-    // set to measure 1.1 reference
-    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
-    // average a number of samples
-    uint16_t sum = 0;
-    uint8_t num = 0;
-    for (uint8_t n = 0; n < 20; n++)
-    {
-        ADCSRA |= _BV(ADSC);
-        loop_until_bit_is_clear(ADCSRA, ADSC);
-
-        uint8_t low_11 = ADCL;
-        uint8_t high_11 = ADCH;
-        uint16_t val = low_11 + (high_11 << 8);
-
-        if (n >= 4)
-        {
-            sum += val;
-            num++;
-        }
-    }
-    ADCSRA = 0;
-    PRR |= _BV(PRADC);
-
-    //float res_volts = 1.1 * 1024 * num / sum;
-    //return 1000 * res_volts;
-    return ((uint32_t)1100*1024*num) / sum;
-}
-
-static void
-do_fridge()
-{
-    struct epoch_ticks now;
-    get_epoch_ticks(&now);
-    uint32_t off_time = now.ticks - fridge_off_clock.ticks;
-    bool wort_valid = last_wort != DS18X20_INVALID_DECICELSIUS;
-    bool fridge_valid = last_fridge != DS18X20_INVALID_DECICELSIUS;
-
-    int16_t wort_max = fridge_setpoint + fridge_difference;
-    int16_t wort_min = fridge_setpoint;
-
-    // the fridge min/max only apply if the wort sensor is broken
-    int16_t fridge_min = fridge_setpoint - FRIDGE_AIR_MIN_RANGE;
-    int16_t fridge_max = fridge_setpoint + FRIDGE_AIR_MAX_RANGE;
-
-    uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE);
-    printf_P(PSTR("last_wort %hd (%hd, %hd), last_fridge %hd (%hd, %hd), setpoint %hd, diff %hd, fridge_on %hhu\n"), 
-            last_wort, wort_min, wort_max, 
-            last_fridge, fridge_min, fridge_max, 
-            fridge_setpoint, fridge_difference, fridge_on);
-
-    if (off_time < fridge_delay)
-    {
-        printf_P(PSTR("waiting for fridge delay current %hu, wait %hu\n"),
-                off_time, fridge_delay);
-        return;
-    }
-
-    // handle failure of the wort sensor. if it is a short (intermittent?)
-    // failure we wait until it has been broken for a period of time
-    // (WORT_INVALID_TIME) before doing anything.
-    if (wort_valid)
-    {
-        wort_valid_clock = now;
-    }
-    else
-    {
-        printf_P(PSTR("wort sensor is invalid\n"));
-        uint32_t invalid_time = now.ticks - wort_valid_clock.ticks;
-        if (invalid_time < WORT_INVALID_TIME)
-        {
-            printf("only been invalid for %ld, waiting\n", invalid_time);
-            return;
-        }
-    }
-
-    if (!fridge_valid)
-    {
-        printf_P(PSTR("fridge sensor is invalid\n"));
-    }
-
-    if (fridge_on)
-    {
-        bool turn_off = false;
-        uint16_t on_time = now.ticks - fridge_on_clock.ticks;
-
-        uint16_t overshoot = 0;
-        if (on_time > overshoot_delay)
-        {
-            overshoot = overshoot_factor * MIN(OVERSHOOT_MAX_DIV, on_time) / OVERSHOOT_MAX_DIV;
-        }
-
-        printf_P(PSTR("on_time %hu, overshoot %hu\n"), on_time, overshoot);
-
-        // wort has cooled enough. will probably cool a bit more by itself
-        if (wort_valid)
-        {
-            if ((last_wort - overshoot) < fridge_setpoint)
-            {
-                printf_P(PSTR("wort has cooled enough, overshoot %hu on_time %hu\n"), overshoot, on_time);
-                turn_off = true;
-            }
-        }
-        else
-        {
-            if (fridge_valid && last_fridge < fridge_min)
-            {
-                printf_P(PSTR("fridge off fallback\n"));
-                turn_off = true;
-            }
-        }
-
-        if (turn_off)
-        {
-            // too cold, turn off
-            printf_P(PSTR("Turning fridge off\n"));
-            PORT_FRIDGE &= ~_BV(PIN_FRIDGE);
-            fridge_off_clock = now;
-        }
-    }
-    else
-    {
-        bool turn_on = false;
-
-        if (wort_valid)
-        {
-            if (last_wort >= wort_max)
-            {
-                printf_P(PSTR("wort is too hot\n"));
-                turn_on = true;
-            }
-        }
-        else
-        {
-            if (fridge_valid && last_fridge >= fridge_max)
-            {
-                printf_P(PSTR("fridge on fallback\n"));
-                turn_on = true;
-            }
-        }
-
-        if (turn_on)
-        {
-            // too hot, turn on
-            printf_P(PSTR("Turning fridge on\n"));
-            PORT_FRIDGE |= _BV(PIN_FRIDGE);
-            fridge_on_clock = now;
-        }
-    }
-}
-
-static void
-do_measurement()
-{
-    blink();
-
-    /* Take the timer here since deep_sleep() below could take 6 seconds */
-    get_epoch_ticks(&last_measurement_clock);
-    if (n_measurements == 0)
-    {
-        first_measurement_clock = last_measurement_clock;
-    }
-
-    simple_ds18b20_start_meas(NULL);
-    _delay_ms(DS18B20_TCONV_12BIT);
-
-    if (n_measurements == max_measurements)
-    {
-        n_measurements = 0;
-    }
-
-    for (uint8_t s = 0; s < n_sensors; s++)
-    {
-        uint16_t reading;
-        uint8_t ret = simple_ds18b20_read_raw(sensor_id[s], &reading);
-        if (ret != DS18X20_OK)
-        {
-            reading = VALUE_BROKEN;
-        }
-        set_measurement(s, n_measurements, reading);
-
-        if (memcmp(sensor_id[s], fridge_id, sizeof(fridge_id)) == 0)
-        {
-            last_fridge = ds18b20_raw16_to_decicelsius(reading);
-        }
-        if (memcmp(sensor_id[s], wort_id, sizeof(wort_id)) == 0)
-        {
-            last_wort = ds18b20_raw16_to_decicelsius(reading);
-        }
-    }
-
-    n_measurements++;
-}
-
-static void
-do_comms()
-{
-    get_epoch_ticks(&last_comms_clock);
-
-    // turn on bluetooth
-    set_aux_power(1);
-    // avoid receiving rubbish, perhaps
-    _delay_ms(50);
-    uart_on();
-    
-    // write sd card here? same 3.3v regulator...
-    
-    for (comms_timeout = wake_secs; 
-        comms_timeout > 0 || stay_awake;  
-        )
-    {
-        if (need_measurement)
-        {
-            need_measurement = 0;
-            do_measurement();
-            do_fridge();
-            continue;
-        }
-
-        if (have_cmd)
-        {
-            have_cmd = 0;
-            read_handler();
-            continue;
-        }
-
-        // wait for commands from the master
-        idle_sleep();
-    }
-
-    uart_off();
-    // in case bluetooth takes time to flush
-    _delay_ms(100);
-    set_aux_power(0);
-}
-
-static void
-blink()
-{
-    PORT_LED &= ~_BV(PIN_LED);
-    _delay_ms(1);
-    PORT_LED |= _BV(PIN_LED);
-}
-
-static void
-long_delay(int ms)
-{
-    int iter = ms / 100;
-
-    for (int i = 0; i < iter; i++)
-    {
-        _delay_ms(100);
-    }
-}
-
-ISR(BADISR_vect)
-{
-    //uart_on();
-    printf_P(PSTR("Bad interrupt\n"));
-}
-
-int main(void)
-{
-    setup_chip();
-    blink();
-
-    set_aux_power(0);
-
-    stdout = &mystdout;
-    uart_on();
-
-    printf(PSTR("Started.\n"));
-
-    load_params();
-
-    init_sensors();
-
-    uart_off();
-
-    // turn off everything except timer2
-    PRR = _BV(PRTWI) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC);
-
-    setup_tick_counter();
-
-    sei();
-
-    need_comms = 1;
-    need_measurement = 1;
-
-    stay_awake = 1;
-
-    for(;;)
-    {
-        if (button_pressed)
-        {
-            // debounce
-            _delay_ms(200);
-            need_comms = 1;
-            comms_timeout = wake_secs;
-            button_pressed = 0;
-            continue;
-        }
-
-        if (need_comms)
-        {
-            need_comms = 0;
-            do_comms();
-            continue;
-        }
-
-        if (need_measurement)
-        {
-            need_measurement = 0;
-            do_measurement();
-            do_fridge();
-            continue;
-        }
-
-        deep_sleep();
-    }
-
-    return 0;   /* never reached */
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/Makefile	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,112 @@
+# Name: Makefile
+# Author: <insert your name here>
+# Copyright: <insert your copyright message here>
+# License: <insert your license reference here>
+
+# This is a prototype Makefile. Modify it according to your needs.
+# You should at least check the settings for
+# DEVICE ....... The AVR device you compile for
+# CLOCK ........ Target AVR clock rate in Hertz
+# OBJECTS ...... The object files created from your source files. This list is
+#                usually the same as the list of source files with suffix ".o".
+# PROGRAMMER ... Options to avrdude which define the hardware you use for
+#                uploading to the AVR and the interface where this hardware
+#                is connected. We recommend that you leave it undefined and
+#                add settings like this to your ~/.avrduderc file:
+#                   default_programmer = "stk500v2"
+#                   default_serial = "avrdoper"
+# FUSES ........ Parameters for avrdude to flash the fuses appropriately.
+
+DEVICE     = atmega328
+PROGDEVICE     = atmega328p
+CLOCK      = 2000000
+PROGRAMMER = #-c stk500v2 -P avrdoper
+PROGRAMMER = -c stk500 -P ~/dev/stk500 -p $(PROGDEVICE)  -B 2
+SOURCE_1WIRE = onewire.c simple_ds18b20.c crc8.c
+SOURCE    = main.c
+SOURCE += $(SOURCE_1WIRE)
+LIBS       = -lm
+
+# default but 2mhz
+FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0x62:m
+
+# ATMega8 fuse bits used above (fuse bits for other devices are different!):
+# Example for 8 MHz internal oscillator
+# Fuse high byte:
+# 0xd9 = 1 1 0 1   1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
+#        ^ ^ ^ ^   ^ ^ ^------ BOOTSZ0
+#        | | | |   | +-------- BOOTSZ1
+#        | | | |   +---------- EESAVE (set to 0 to preserve EEPROM over chip erase)
+#        | | | +-------------- WDTON
+#        | | +---------------- SPIEN (if set to 1, serial programming is disabled)
+#        | +------------------ DWEN
+#        +-------------------- RSTDISBL (if set to 0, RESET pin is disabled)
+# Fuse low byte:
+# 0x62 = 0 1 1 0   0 0 1 0
+#        ^ ^ \ /   \--+--/
+#        | |  |       +------- CKSEL 3..0 (8M internal RC)
+#        | |  +--------------- SUT 1..0 (slowly rising power)
+#        | +------------------ CKOUT
+#        +-------------------- CLKDIV8
+#
+# For computing fuse byte values for other devices and options see
+# the fuse bit calculator at http://www.engbedded.com/fusecalc/
+
+
+# Tune the lines below only if you know what you are doing:
+
+AVRDUDE = avrdude $(PROGRAMMER) 
+COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 -mcall-prologues -fdata-sections -ffunction-sections  -Wl,--gc-sections -Wl,--relax --combine -fwhole-program  -Wl,-u,vfprintf -lprintf_flt -lm
+
+# symbolic targets:
+all:	main.hex
+
+.c.o:
+	$(COMPILE) -c $< -o $@
+
+.S.o:
+	$(COMPILE) -x assembler-with-cpp -c $< -o $@
+# "-x assembler-with-cpp" should not be necessary since this is the default
+# file type for the .S (with capital S) extension. However, upper case
+# characters are not always preserved on Windows. To ensure WinAVR
+# compatibility define the file type manually.
+
+.c.s:
+	$(COMPILE) -S $< -o $@
+
+flash:	all
+	$(AVRDUDE) -U flash:w:main.hex:i
+
+checkprog:	
+	$(AVRDUDE) -v 
+
+fuse:
+	$(AVRDUDE) $(FUSES)
+
+# Xcode uses the Makefile targets "", "clean" and "install"
+install: flash 
+
+# if you use a bootloader, change the command below appropriately:
+load: all
+	bootloadHID main.hex
+
+clean:
+	rm -f main.hex main.elf $(OBJECTS)
+
+# file targets:
+main.elf: $(SOURCE)
+	$(COMPILE) -o main.elf $(SOURCE) $(LIBS)
+
+main.hex: main.elf
+	rm -f main.hex
+	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
+	avr-size --format=avr --mcu=$(DEVICE) main.elf
+# If you have an EEPROM section, you must also create a hex file for the
+# EEPROM and add it to the "flash" target.
+
+# Targets for code debugging and analysis:
+disasm:	main.elf
+	avr-objdump -d main.elf
+
+cpp:
+	$(COMPILE) -E main.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/crc8.c	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,63 @@
+/* please read copyright-notice at EOF */
+
+#include <stdint.h>
+
+#define CRC8INIT    0x00
+#define CRC8POLY    0x18              //0X18 = X^8+X^5+X^4+X^0
+
+uint8_t crc8( uint8_t *data, uint16_t number_of_bytes_in_data )
+{
+	uint8_t  crc;
+	uint16_t loop_count;
+	uint8_t  bit_counter;
+	uint8_t  b;
+	uint8_t  feedback_bit;
+	
+	crc = CRC8INIT;
+
+	for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++)
+	{
+		b = data[loop_count];
+		
+		bit_counter = 8;
+		do {
+			feedback_bit = (crc ^ b) & 0x01;
+	
+			if ( feedback_bit == 0x01 ) {
+				crc = crc ^ CRC8POLY;
+			}
+			crc = (crc >> 1) & 0x7F;
+			if ( feedback_bit == 0x01 ) {
+				crc = crc | 0x80;
+			}
+		
+			b = b >> 1;
+			bit_counter--;
+		
+		} while (bit_counter > 0);
+	}
+	
+	return crc;
+}
+
+/*
+This code is from Colin O'Flynn - Copyright (c) 2002 
+only minor changes by M.Thomas 9/2004
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/crc8.h	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,40 @@
+#ifndef CRC8_H_
+#define CRC8_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+uint8_t crc8( uint8_t* data, uint16_t number_of_bytes_in_data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*
+This is based on code from :
+
+Copyright (c) 2002 Colin O'Flynn
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/ds18x20.h	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,140 @@
+#ifndef DS18X20_H_
+#define DS18X20_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+
+// DS18x20 EERPROM support disabled(0) or enabled(1) :
+#define DS18X20_EEPROMSUPPORT     1
+// decicelsius functions disabled(0) or enabled(1):
+#define DS18X20_DECICELSIUS       1
+// max. resolution functions disabled(0) or enabled(1):
+#define DS18X20_MAX_RESOLUTION    1
+// extended output via UART disabled(0) or enabled(1) :
+#define DS18X20_VERBOSE           1
+
+
+/* return values */
+#define DS18X20_OK                0x00
+#define DS18X20_ERROR             0x01
+#define DS18X20_START_FAIL        0x02
+#define DS18X20_ERROR_CRC         0x03
+
+#define DS18X20_INVALID_DECICELSIUS  2000
+
+#define DS18X20_POWER_PARASITE    0x00
+#define DS18X20_POWER_EXTERN      0x01
+
+#define DS18X20_CONVERSION_DONE   0x00
+#define DS18X20_CONVERTING        0x01
+
+/* DS18X20 specific values (see datasheet) */
+#define DS18S20_FAMILY_CODE       0x10
+#define DS18B20_FAMILY_CODE       0x28
+#define DS1822_FAMILY_CODE        0x22
+
+#define DS18X20_CONVERT_T         0x44
+#define DS18X20_READ              0xBE
+#define DS18X20_WRITE             0x4E
+#define DS18X20_EE_WRITE          0x48
+#define DS18X20_EE_RECALL         0xB8
+#define DS18X20_READ_POWER_SUPPLY 0xB4
+
+#define DS18B20_CONF_REG          4
+#define DS18B20_9_BIT             0
+#define DS18B20_10_BIT            (1<<5)
+#define DS18B20_11_BIT            (1<<6)
+#define DS18B20_12_BIT            ((1<<6)|(1<<5))
+#define DS18B20_RES_MASK          ((1<<6)|(1<<5))
+
+// undefined bits in LSB if 18B20 != 12bit
+#define DS18B20_9_BIT_UNDF        ((1<<0)|(1<<1)|(1<<2))
+#define DS18B20_10_BIT_UNDF       ((1<<0)|(1<<1))
+#define DS18B20_11_BIT_UNDF       ((1<<0))
+#define DS18B20_12_BIT_UNDF       0
+
+// conversion times in milliseconds
+#define DS18B20_TCONV_12BIT       750
+#define DS18B20_TCONV_11BIT       DS18B20_TCONV_12_BIT/2
+#define DS18B20_TCONV_10BIT       DS18B20_TCONV_12_BIT/4
+#define DS18B20_TCONV_9BIT        DS18B20_TCONV_12_BIT/8
+#define DS18S20_TCONV             DS18B20_TCONV_12_BIT
+
+// constant to convert the fraction bits to cel*(10^-4)
+#define DS18X20_FRACCONV          625
+
+// scratchpad size in bytes
+#define DS18X20_SP_SIZE           9
+
+// DS18X20 EEPROM-Support
+#define DS18X20_WRITE_SCRATCHPAD  0x4E
+#define DS18X20_COPY_SCRATCHPAD   0x48
+#define DS18X20_RECALL_E2         0xB8
+#define DS18X20_COPYSP_DELAY      10 /* ms */
+#define DS18X20_TH_REG            2
+#define DS18X20_TL_REG            3
+
+#define DS18X20_DECIMAL_CHAR      '.'
+
+
+extern uint8_t DS18X20_find_sensor(uint8_t *diff, 
+	uint8_t id[]);
+extern uint8_t DS18X20_get_power_status(uint8_t id[]);
+extern uint8_t DS18X20_start_meas( uint8_t with_external,
+	uint8_t id[]);
+// returns 1 if conversion is in progress, 0 if finished
+// not available when parasite powered
+extern uint8_t DS18X20_conversion_in_progress(void);
+
+
+#if DS18X20_DECICELSIUS
+extern uint8_t DS18X20_read_decicelsius( uint8_t id[],
+	int16_t *decicelsius );
+extern uint8_t DS18X20_read_decicelsius_single( uint8_t familycode,
+	int16_t *decicelsius );
+extern uint8_t DS18X20_format_from_decicelsius( int16_t decicelsius, 
+	char s[], uint8_t n);
+#endif /* DS18X20_DECICELSIUS */
+
+
+#if DS18X20_MAX_RESOLUTION
+// temperature unit for max. resolution is �C * 10e-4
+// examples: -250625 -> -25.0625�C, 1250000 -> 125.0000 �C
+extern uint8_t DS18X20_read_maxres( uint8_t id[],
+	int32_t *temperaturevalue );
+extern uint8_t DS18X20_read_maxres_single( uint8_t familycode,
+	int32_t *temperaturevalue );
+extern uint8_t DS18X20_format_from_maxres( int32_t temperaturevalue, 
+	char s[], uint8_t n);
+#endif /* DS18X20_MAX_RESOLUTION */
+
+
+#if DS18X20_EEPROMSUPPORT
+// write th, tl and config-register to scratchpad (config ignored on DS18S20)
+uint8_t DS18X20_write_scratchpad( uint8_t id[], 
+	uint8_t th, uint8_t tl, uint8_t conf);
+// read scratchpad into array SP
+uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n);
+// copy values int scratchpad into DS18x20 eeprom
+uint8_t DS18X20_scratchpad_to_eeprom( uint8_t with_power_extern,
+	uint8_t id[] );
+// copy values from DS18x20 eeprom into scratchpad
+uint8_t DS18X20_eeprom_to_scratchpad( uint8_t id[] );
+#endif /* DS18X20_EEPROMSUPPORT */
+
+
+#if DS18X20_VERBOSE
+extern void DS18X20_show_id_uart( uint8_t *id, size_t n );
+extern uint8_t DS18X20_read_meas_all_verbose( void );
+#endif /* DS18X20_VERBOSE */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/main.c	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,1200 @@
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <avr/pgmspace.h>
+#include <avr/eeprom.h>
+#include <avr/wdt.h>
+#include <util/atomic.h>
+#include <util/crc16.h>
+
+#include "simple_ds18b20.h"
+#include "onewire.h"
+
+// configuration params
+// - measurement interval
+// - transmit interval
+// - bluetooth params
+// - number of sensors (and range?)
+
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+// TICK should be 8 or less (8 untested). all timers need
+// to be a multiple.
+
+#define TICK 6
+// we have 1024 prescaler, 32768 crystal.
+#define SLEEP_COMPARE (32*TICK-1)
+
+#define VALUE_NOSENSOR 0x07D0 // 125 degrees
+#define VALUE_BROKEN 0x07D1 // 125.0625
+
+#define OVERSHOOT_MAX_DIV 1800.0 // 30 mins
+#define WORT_INVALID_TIME 900 // 15 mins
+// fridge min/max are only used if the wort sensor is invalid
+#define FRIDGE_AIR_MIN_RANGE 40 // 4º
+#define FRIDGE_AIR_MAX_RANGE 40 // 4º
+
+#define BAUD 19200
+#define UBRR ((F_CPU)/8/(BAUD)-1)
+
+#define PORT_LED PORTC
+#define DDR_LED DDRC
+#define PIN_LED PC4
+
+#define PORT_SHDN PORTD
+#define DDR_SHDN DDRD
+#define PIN_SHDN PD7
+
+#define PORT_FRIDGE PORTD
+#define DDR_FRIDGE DDRD
+#define PIN_FRIDGE PD6
+
+// total amount of 16bit values available for measurements.
+// adjust emperically, be sure to allow enough stack space too
+#define TOTAL_MEASUREMENTS 800
+
+// each sensor slot uses 8 bytes
+#define MAX_SENSORS 6
+
+// fixed at 8, have a shorter name
+#define ID_LEN OW_ROMCODE_SIZE
+
+// #define HAVE_UART_ECHO
+
+// stores a value of clock_epoch combined with the remainder of TCNT2,
+// for 1/32 second accuracy
+struct epoch_ticks
+{
+    uint32_t ticks;
+    // remainder
+    uint8_t rem;
+};
+
+// eeprom-settable parameters. all timeouts should
+// be a multiple of TICK (6 seconds probably)
+static uint16_t measure_wake = 61; // not a divisor of comms_wake
+static uint16_t comms_wake = 600;
+static uint8_t wake_secs = 30;
+// decidegrees
+static int16_t fridge_setpoint = 180; // 18.0ºC
+static uint16_t fridge_difference = 3; // 0.3ºC
+static uint16_t fridge_delay = 600; // seconds
+
+static uint16_t overshoot_delay = 720; // 12 mins
+static uint8_t overshoot_factor = 10; // 1.0ºC
+
+// ---- Atomic guards required accessing these variables
+// clock_epoch in seconds
+static uint32_t clock_epoch;
+static uint16_t comms_count;
+static uint16_t measure_count;
+// ---- End atomic guards required
+
+static uint16_t n_measurements;
+
+// calculated at startup as TOTAL_MEASUREMENTS/n_sensors
+static uint16_t max_measurements;
+
+static uint16_t measurements[TOTAL_MEASUREMENTS];
+
+static struct epoch_ticks first_measurement_clock;
+// last_measurement_clock is redundant but checks that we're not missing
+// samples
+static struct epoch_ticks last_measurement_clock;
+static struct epoch_ticks last_comms_clock;
+
+// boolean flags
+static uint8_t need_measurement;
+static uint8_t need_comms;
+static uint8_t uart_enabled;
+static uint8_t stay_awake;
+static uint8_t button_pressed;
+
+// counts down from WAKE_SECS to 0, goes to deep sleep when hits 0
+static uint8_t comms_timeout;
+
+static uint8_t readpos;
+static char readbuf[30];
+static uint8_t have_cmd;
+
+static uint8_t n_sensors;
+static uint8_t sensor_id[MAX_SENSORS][ID_LEN];
+
+static int16_t last_fridge = DS18X20_INVALID_DECICELSIUS;
+static int16_t last_wort = DS18X20_INVALID_DECICELSIUS;
+static struct epoch_ticks fridge_off_clock = {0};
+static struct epoch_ticks fridge_on_clock = {0};
+static struct epoch_ticks wort_valid_clock = {0};
+
+int uart_putchar(char c, FILE *stream);
+static void long_delay(int ms);
+static void blink();
+static uint16_t adc_vcc();
+
+static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
+        _FDEV_SETUP_WRITE);
+
+static uint16_t crc_out;
+static FILE _crc_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
+        _FDEV_SETUP_WRITE);
+// convenience
+static FILE *crc_stdout = &_crc_stdout;
+
+
+// thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/
+#define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size))
+#define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst))
+#define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size))
+#define eeprom_write(src, eeprom_field) { eeprom_write_from(&src, eeprom_field, sizeof(src)); }
+
+#define EXPECT_MAGIC 0x67c9
+
+struct __attribute__ ((__packed__)) __eeprom_data {
+    uint16_t measure_wake;
+    uint16_t comms_wake;
+    uint8_t wake_secs;
+
+    int16_t fridge_setpoint; // decidegrees
+    uint16_t fridge_difference; // decidegrees
+    uint16_t fridge_delay;
+
+    uint16_t overshoot_delay;
+    uint8_t overshoot_factor; // decidegrees
+
+#if 0
+    static uint8_t wort_id[ID_LEN];
+    static uint8_t fridge_id[ID_LEN];
+#endif
+
+    uint16_t magic;
+};
+
+static const uint8_t fridge_id[ID_LEN] = 
+    {0x28,0xCE,0xB2,0x1A,0x03,0x00,0x00,0x99};
+static const uint8_t wort_id[ID_LEN] = 
+    {0x28,0x49,0xBC,0x1A,0x03,0x00,0x00,0x54};
+
+static void deep_sleep();
+
+// 0 or 1
+static uint8_t
+is_fridge_on()
+{
+    if (PORT_FRIDGE & _BV(PIN_FRIDGE))
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+// Very first setup
+static void
+setup_chip()
+{
+    cli();
+
+    // stop watchdog timer (might have been used to cause a reset)
+    wdt_reset();
+    MCUSR &= ~_BV(WDRF);
+    WDTCSR |= _BV(WDCE) | _BV(WDE);
+    WDTCSR = 0;
+
+    // Set clock to 2mhz
+    CLKPR = _BV(CLKPCE);
+    // divide by 4
+    CLKPR = _BV(CLKPS1);
+
+    // enable pullups
+    PORTB = 0xff; // XXX change when using SPI
+    PORTD = 0xff;
+    PORTC = 0xff;
+
+    // 3.3v power for bluetooth and SD
+    DDR_LED |= _BV(PIN_LED);
+    DDR_SHDN |= _BV(PIN_SHDN);
+
+    PORT_FRIDGE &= ~_BV(PIN_FRIDGE);
+    DDR_FRIDGE |= _BV(PIN_FRIDGE);
+
+    // set pullup
+    PORTD |= _BV(PD2);
+    // INT0 setup
+    EICRA = (1<<ISC01); // falling edge - data sheet says it won't work?
+    EIMSK = _BV(INT0);
+
+    // comparator disable
+    ACSR = _BV(ACD);
+
+    // disable adc pin input buffers
+    DIDR0 = 0x3F; // acd0-adc5
+    DIDR1 = (1<<AIN1D)|(1<<AIN0D); // ain0/ain1
+
+    sei();
+}
+
+static void
+set_aux_power(uint8_t on)
+{
+    if (on)
+    {
+        PORT_SHDN &= ~_BV(PIN_SHDN);
+    }
+    else
+    {
+        PORT_SHDN |= _BV(PIN_SHDN);
+    }
+}
+
+static void
+get_epoch_ticks(struct epoch_ticks *t)
+{
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+    {
+        t->ticks = clock_epoch;
+        t->rem = TCNT2;
+    }
+}
+
+static void 
+set_measurement(uint8_t sensor, uint16_t measurement, uint16_t reading)
+{
+    measurements[sensor*max_measurements + measurement] = reading;
+}
+
+static uint16_t 
+get_measurement(uint8_t sensor, uint16_t measurement)
+{
+    return measurements[sensor*max_measurements + measurement];
+}
+
+static void
+setup_tick_counter()
+{
+    // set up counter2. 
+    // COM21 COM20 Set OC2 on Compare Match (p116)
+    // WGM21 Clear counter on compare
+    //TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21);
+    // toggle on match
+    TCCR2A = _BV(COM2A0);
+    // CS22 CS21 CS20  clk/1024
+    TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
+    // set async mode
+    ASSR |= _BV(AS2);
+    TCNT2 = 0;
+    OCR2A = SLEEP_COMPARE;
+    // interrupt
+    TIMSK2 = _BV(OCIE2A);
+}
+
+static void 
+uart_on()
+{
+    // Power reduction register
+    PRR &= ~_BV(PRUSART0);
+ 
+    // All of this needs to be done each time after turning off the PRR
+    // baud rate
+    UBRR0H = (unsigned char)(UBRR >> 8);
+    UBRR0L = (unsigned char)UBRR;
+    // set 2x clock, improves accuracy of UBRR
+    UCSR0A |= _BV(U2X0);
+    UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
+    //8N1
+    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
+    uart_enabled = 1;
+}
+
+static void 
+uart_off()
+{
+    // Turn off interrupts and disable tx/rx
+    UCSR0B = 0;
+    uart_enabled = 0;
+
+    // Power reduction register
+    PRR |= _BV(PRUSART0);
+}
+
+int 
+uart_putchar(char c, FILE *stream)
+{
+    if (!uart_enabled)
+    {
+        return EOF;
+    }
+    // XXX could perhaps sleep in the loop for power.
+    if (c == '\n')
+    {
+        loop_until_bit_is_set(UCSR0A, UDRE0);
+        UDR0 = '\r';
+    }
+    loop_until_bit_is_set(UCSR0A, UDRE0);
+    UDR0 = c;
+    if (stream == crc_stdout)
+    {
+        crc_out = _crc_ccitt_update(crc_out, c);
+    }
+    if (c == '\r')
+    {
+        loop_until_bit_is_set(UCSR0A, UDRE0);
+        UDR0 = '\n';
+        if (stream == crc_stdout)
+        {
+            crc_out = _crc_ccitt_update(crc_out, '\n');
+        }
+    }
+    return (unsigned char)c;
+}
+
+static void
+cmd_fetch()
+{
+    crc_out = 0;
+
+    fprintf_P(crc_stdout, PSTR("START\n"));
+    {
+        struct epoch_ticks now;
+        get_epoch_ticks(&now);
+        fprintf_P(crc_stdout, PSTR("now=%lu\n"), now.ticks);
+        fprintf_P(crc_stdout, PSTR("now_rem=%hhu\n"), now.rem);
+    }
+    fprintf_P(crc_stdout, PSTR("time_step=%hu\n"), measure_wake);
+    fprintf_P(crc_stdout, PSTR("first_time=%lu\n"), first_measurement_clock.ticks);
+    fprintf_P(crc_stdout, PSTR("first_time_rem=%hhu\n"), first_measurement_clock.rem);
+    fprintf_P(crc_stdout, PSTR("last_time=%lu\n"),  last_measurement_clock.ticks);
+    fprintf_P(crc_stdout, PSTR("last_time_rem=%hhu\n"),  last_measurement_clock.rem);
+    fprintf_P(crc_stdout, PSTR("comms_time=%lu\n"), last_comms_clock.ticks);
+    fprintf_P(crc_stdout, PSTR("comms_time_rem=%hhu\n"), last_comms_clock.rem);
+    fprintf_P(crc_stdout, PSTR("voltage=%hu\n"), adc_vcc());
+    fprintf_P(crc_stdout, PSTR("measure=%hu\n"), measure_wake);
+    fprintf_P(crc_stdout, PSTR("comms=%hu\n"), comms_wake);
+    fprintf_P(crc_stdout, PSTR("wake=%hhu\n"), wake_secs);
+    fprintf_P(crc_stdout, PSTR("fridge=%.1f\n"), fridge_setpoint/10.0);
+    fprintf_P(crc_stdout, PSTR("fridge_diff=%.1f\n"), fridge_difference/10.0);
+    fprintf_P(crc_stdout, PSTR("fridge_delay=%hu\n"), fridge_delay);
+    fprintf_P(crc_stdout, PSTR("overshoot_factor=%.1f\n"), overshoot_factor/10.0);
+    fprintf_P(crc_stdout, PSTR("overshoot_delay=%hu\n"), overshoot_delay);
+    fprintf_P(crc_stdout, PSTR("fridge_status=%hhu\n"), is_fridge_on());
+    fprintf_P(crc_stdout, PSTR("fridge_last_on=%lu\n"), fridge_on_clock.ticks);
+    fprintf_P(crc_stdout, PSTR("fridge_last_off=%lu\n"), fridge_off_clock.ticks);
+    fprintf_P(crc_stdout, PSTR("last_fridge=%hu\n"), last_fridge);
+    fprintf_P(crc_stdout, PSTR("last_wort=%hu\n"), last_wort);
+    fprintf_P(crc_stdout, PSTR("tick_secs=%d\n"), TICK);
+    fprintf_P(crc_stdout, PSTR("tick_wake=%d\n"), SLEEP_COMPARE);
+    fprintf_P(crc_stdout, PSTR("maxsens=%hhu\n"), MAX_SENSORS);
+    fprintf_P(crc_stdout, PSTR("totalmeas=%hu\n"), TOTAL_MEASUREMENTS);
+    fprintf_P(crc_stdout, PSTR("sensors=%hhu\n"), n_sensors);
+    for (uint8_t s = 0; s < n_sensors; s++)
+    {
+        fprintf_P(crc_stdout, PSTR("sensor_id%hhu="), s);
+        printhex(sensor_id[s], ID_LEN, crc_stdout);
+        fputc('\n', crc_stdout);
+    }
+    fprintf_P(crc_stdout, PSTR("measurements=%hu\n"), n_measurements);
+    for (uint16_t n = 0; n < n_measurements; n++)
+    {
+        fprintf_P(crc_stdout, PSTR("meas%hu="), n);
+        for (uint8_t s = 0; s < n_sensors; s++)
+        {
+            fprintf_P(crc_stdout, PSTR(" %04hx"), get_measurement(s, n));
+        }
+        fputc('\n', crc_stdout);
+    }
+    fprintf_P(crc_stdout, PSTR("END\n"));
+    fprintf_P(stdout, PSTR("CRC=%hu\n"), crc_out);
+}
+
+static void
+cmd_clear()
+{
+    n_measurements = 0;
+    printf_P(PSTR("cleared\n"));
+}
+
+static void
+cmd_btoff()
+{
+    uint8_t rem;
+    uint16_t count_copy;
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+    {
+        count_copy = comms_count;
+        rem = TCNT2;
+    }
+    printf_P(PSTR("next_wake=%hu,"), comms_wake-count_copy);
+    printf_P(PSTR("rem=%hhu,"), rem);
+    printf_P(PSTR("tick_secs=%hhu,"), TICK);
+    printf_P(PSTR("tick_wake=%hhu\n"), SLEEP_COMPARE);
+    _delay_ms(100);
+    comms_timeout = 0;
+    stay_awake = 0;
+}
+
+static void
+cmd_reset()
+{
+    printf_P(PSTR("reset\n"));
+    _delay_ms(100);
+    cli(); // disable interrupts 
+    wdt_enable(WDTO_15MS); // enable watchdog 
+    while(1); // wait for watchdog to reset processor 
+}
+
+static void
+cmd_measure()
+{
+    printf_P(PSTR("measuring\n"));
+    need_measurement = 1;
+}
+
+static void
+cmd_sensors()
+{
+    uint8_t ret = simple_ds18b20_start_meas(NULL);
+    printf_P(PSTR("All sensors, ret %hhu, waiting...\n"), ret);
+    long_delay(DS18B20_TCONV_12BIT);
+    simple_ds18b20_read_all();
+}
+
+static void
+init_sensors()
+{
+    uint8_t id[OW_ROMCODE_SIZE];
+    printf_P(PSTR("init sensors\n"));
+    ow_reset();
+    for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
+    {
+        diff = ow_rom_search( diff, &id[0] );
+        if( diff == OW_PRESENCE_ERR ) {
+            printf_P( PSTR("No Sensor found\r") );
+            return;
+        }
+        
+        if( diff == OW_DATA_ERR ) {
+            printf_P( PSTR("Bus Error\r") );
+            return;
+        }
+
+        if (n_sensors < MAX_SENSORS)
+        {
+            memcpy(sensor_id[n_sensors], id, ID_LEN);
+            printf_P(PSTR("Added sensor %hhu : "), n_sensors);
+            printhex(id, ID_LEN, stdout);
+            putchar('\n');
+            n_sensors++;
+        }
+        else
+        {
+            printf_P(PSTR("Too many sensors\n"));
+        }
+    }
+
+    max_measurements = TOTAL_MEASUREMENTS / n_sensors;
+}
+
+static void
+load_params()
+{
+    uint16_t magic;
+    eeprom_read(magic, magic);
+    if (magic == EXPECT_MAGIC)
+    {
+        eeprom_read(measure_wake, measure_wake);
+        eeprom_read(comms_wake, comms_wake);
+        eeprom_read(wake_secs, wake_secs);
+        eeprom_read(fridge_setpoint, fridge_setpoint);
+        eeprom_read(fridge_difference, fridge_difference);
+        eeprom_read(fridge_delay, fridge_delay);
+        eeprom_read(overshoot_delay, overshoot_delay);
+        eeprom_read(overshoot_factor, overshoot_factor);
+    }
+}
+
+static void
+cmd_get_params()
+{
+    printf_P(PSTR("measure %hu\n"), measure_wake);
+    printf_P(PSTR("comms %hu\n"), comms_wake);
+    printf_P(PSTR("wake %hhu\n"), wake_secs);
+    printf_P(PSTR("tick %d\n"), TICK);
+    printf_P(PSTR("fridge %.1fº\n"), fridge_setpoint / 10.0f);
+    printf_P(PSTR("fridge difference %.1fº\n"), fridge_difference / 10.0f);
+    printf_P(PSTR("fridge_delay %hu\n"), fridge_delay);
+    printf_P(PSTR("overshoot factor %.1fº\n"), overshoot_factor / 10.0f);
+    printf_P(PSTR("overshoot delay %hu\n"), overshoot_delay);
+    printf_P(PSTR("sensors %hhu (%hhu)\n"), 
+            n_sensors, MAX_SENSORS);
+    printf_P(PSTR("meas %hu (%hu)\n"),
+            max_measurements, TOTAL_MEASUREMENTS);
+}
+
+static void
+cmd_set_params(const char *params)
+{
+    uint16_t new_measure_wake;
+    uint16_t new_comms_wake;
+    uint8_t new_wake_secs;
+    int ret = sscanf_P(params, PSTR("%hu %hu %hhu"),
+            &new_measure_wake, &new_comms_wake, &new_wake_secs);
+
+    if (ret != 3)
+    {
+        printf_P(PSTR("Bad values\n"));
+    }
+    else
+    {
+        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+        {
+            eeprom_write(new_measure_wake, measure_wake);
+            eeprom_write(new_comms_wake, comms_wake);
+            eeprom_write(new_wake_secs, wake_secs);
+            uint16_t magic = EXPECT_MAGIC;
+            eeprom_write(magic, magic);
+        }
+        printf_P(PSTR("set_params for next boot\n"));
+        printf_P(PSTR("measure %hu comms %hu wake %hhu\n"),
+                new_measure_wake, new_comms_wake, new_wake_secs);
+    }
+}
+
+// returns true if eeprom was written
+static bool
+set_initial_eeprom()
+{
+    uint16_t magic;
+    eeprom_read(magic, magic);
+    if (magic == EXPECT_MAGIC)
+    {
+        return false;
+    }
+
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+    {
+        eeprom_write(measure_wake, measure_wake);
+        eeprom_write(comms_wake, comms_wake);
+        eeprom_write(wake_secs, wake_secs);
+        eeprom_write(fridge_setpoint, fridge_setpoint);
+        eeprom_write(fridge_difference, fridge_difference);
+        eeprom_write(fridge_delay, fridge_delay);
+        eeprom_write(overshoot_delay, overshoot_delay);
+        eeprom_write(overshoot_factor, overshoot_factor);
+        magic = EXPECT_MAGIC;
+        eeprom_write(magic, magic);
+    }
+
+    return true;
+}
+
+static void
+cmd_set_fridge_setpoint(char *params)
+{
+    float new_f = atof(params);
+    if (new_f < 2 || new_f > 30)
+    {
+        printf_P(PSTR("Bad fridge value %f\n"), new_f);
+        return;
+    }
+
+    int16_t old_setpoint = fridge_setpoint;
+
+    fridge_setpoint = new_f * 10;
+    bool written = set_initial_eeprom();
+    if (!written)
+    {
+        if (old_setpoint != fridge_setpoint)
+        {
+            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+            {
+                eeprom_write(fridge_setpoint, fridge_setpoint);
+            }
+        }
+    }
+    printf_P(PSTR("old fridge %.1fº new fridge %.1fº\n"), 
+            old_setpoint / 10.0f, fridge_setpoint / 10.0f);
+}
+
+static void
+cmd_set_fridge_difference(char *params)
+{
+    float new_f = atof(params);
+    if (new_f < 0 || new_f > 30)
+    {
+        printf_P(PSTR("Bad fridge value %f\n"), new_f);
+        return;
+    }
+
+    fridge_difference = new_f * 10;
+    bool written = set_initial_eeprom();
+    if (!written)
+    {
+        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+        {
+            eeprom_write(fridge_difference, fridge_difference);
+        }
+    }
+    printf_P(PSTR("new fridge difference %.1fº\n"), fridge_difference / 10.0f);
+}
+
+static void
+cmd_set_fridge_delay(char *params)
+{
+    uint16_t new_delay = atoi(params);
+    if (new_delay < 5)
+    {
+        printf_P(PSTR("Bad fridge delay %d\n"), new_delay);
+        return;
+    }
+
+    fridge_delay = new_delay;
+    bool written = set_initial_eeprom();
+    if (!written)
+    {
+        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+        {
+            eeprom_write(fridge_delay, fridge_delay);
+        }
+    }
+    printf_P(PSTR("new fridge delay %hu\n"), fridge_delay);
+}
+
+static void
+cmd_set_overshoot_factor(char *params)
+{
+    float new_f = atof(params);
+    if (new_f <= 0 || new_f > 20)
+    {
+        printf_P(PSTR("Bad overshoot factor %f\n"), new_f);
+        return;
+    }
+
+    uint8_t old = overshoot_factor;
+
+    overshoot_factor = new_f * 10;
+    bool written = set_initial_eeprom();
+    if (!written)
+    {
+        if (old != overshoot_factor)
+        {
+            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+            {
+                eeprom_write(overshoot_factor, overshoot_factor);
+            }
+        }
+    }
+    printf_P(PSTR("old factor %.1fº new factor %.1fº\n"), 
+            old / 10.0f, overshoot_factor / 10.0f);
+}
+    
+static void
+cmd_set_overshoot_delay(char *params)
+{
+    uint16_t new_delay = atoi(params);
+    if (new_delay < 5)
+    {
+        printf_P(PSTR("Bad overshoot delay %d\n"), new_delay);
+        return;
+    }
+
+    overshoot_delay = new_delay;
+    bool written = set_initial_eeprom();
+    if (!written)
+    {
+        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+        {
+            eeprom_write(overshoot_delay, overshoot_delay);
+        }
+    }
+    printf_P(PSTR("new overshoot delay %hu\n"), overshoot_delay);
+}
+
+static void
+cmd_awake()
+{
+    stay_awake = 1;
+    printf_P(PSTR("awake\n"));
+}
+
+static void
+read_handler()
+{
+    if (strcmp_P(readbuf, PSTR("fetch")) == 0)
+    {
+        cmd_fetch();
+    }
+    else if (strcmp_P(readbuf, PSTR("clear")) == 0)
+    {
+        cmd_clear();
+    }
+    else if (strcmp_P(readbuf, PSTR("btoff")) == 0)
+    {
+        cmd_btoff();
+    }
+    else if (strcmp_P(readbuf, PSTR("measure")) == 0)
+    {
+        cmd_measure();
+    }
+    else if (strcmp_P(readbuf, PSTR("sensors")) == 0)
+    {
+        cmd_sensors();
+    }
+    else if (strcmp_P(readbuf, PSTR("get_params")) == 0)
+    {
+        cmd_get_params();
+    }
+    else if (strncmp_P(readbuf, PSTR("set_params "), 11) == 0)
+    {
+        cmd_set_params(&readbuf[11]);
+    }
+    else if (strcmp_P(readbuf, PSTR("awake")) == 0)
+    {
+        cmd_awake();
+    }
+    else if (strncmp_P(readbuf, PSTR("fridge_setpoint "), 16) == 0)
+    {
+        cmd_set_fridge_setpoint(&readbuf[16]);
+    }
+    else if (strncmp_P(readbuf, PSTR("fridge_diff "), 12) == 0)
+    {
+        cmd_set_fridge_difference(&readbuf[12]);
+    }
+    else if (strncmp_P(readbuf, PSTR("fridge_delay "), 13) == 0)
+    {
+        cmd_set_fridge_delay(&readbuf[13]);
+    }
+    else if (strncmp_P(readbuf, PSTR("overshoot_delay "), 16) == 0)
+    {
+        cmd_set_overshoot_delay(&readbuf[16]);
+    }
+    else if (strncmp_P(readbuf, PSTR("overshoot_factor "), 17) == 0)
+    {
+        cmd_set_overshoot_factor(&readbuf[17]);
+    }
+    else if (strcmp_P(readbuf, PSTR("reset")) == 0)
+    {
+        cmd_reset();
+    }
+    else
+    {
+        printf_P(PSTR("Bad command '%s'\n"), readbuf);
+    }
+}
+
+ISR(INT0_vect)
+{
+    button_pressed = 1;
+    blink();
+    _delay_ms(100);
+    blink();
+}
+
+
+ISR(USART_RX_vect)
+{
+    char c = UDR0;
+#ifdef HAVE_UART_ECHO
+    uart_putchar(c, NULL);
+#endif
+    if (c == '\r' || c == '\n')
+    {
+        if (readpos > 0)
+        {
+            readbuf[readpos] = '\0';
+            have_cmd = 1;
+            readpos = 0;
+        }
+    }
+    else
+    {
+        readbuf[readpos] = c;
+        readpos++;
+        if (readpos >= sizeof(readbuf))
+        {
+            readpos = 0;
+        }
+    }
+}
+
+ISR(TIMER2_COMPA_vect)
+{
+    TCNT2 = 0;
+    measure_count += TICK;
+    comms_count += TICK;
+
+    clock_epoch += TICK;
+
+    if (comms_timeout != 0)
+    {
+        comms_timeout -= TICK;
+    }
+
+    if (measure_count >= measure_wake)
+    {
+        measure_count = 0;
+        need_measurement = 1;
+    }
+
+    if (comms_count >= comms_wake)
+    {
+        comms_count = 0;
+        need_comms = 1;
+    }
+}
+
+static void
+deep_sleep()
+{
+    // p119 of manual
+    OCR2A = SLEEP_COMPARE;
+    loop_until_bit_is_clear(ASSR, OCR2AUB);
+
+    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
+    sleep_mode();
+}
+
+static void
+idle_sleep()
+{
+    set_sleep_mode(SLEEP_MODE_IDLE);
+    sleep_mode();
+}
+
+static uint16_t
+adc_vcc()
+{
+    PRR &= ~_BV(PRADC);
+    
+    // /16 prescaler
+    ADCSRA = _BV(ADEN) | _BV(ADPS2);
+
+    // set to measure 1.1 reference
+    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
+    // average a number of samples
+    uint16_t sum = 0;
+    uint8_t num = 0;
+    for (uint8_t n = 0; n < 20; n++)
+    {
+        ADCSRA |= _BV(ADSC);
+        loop_until_bit_is_clear(ADCSRA, ADSC);
+
+        uint8_t low_11 = ADCL;
+        uint8_t high_11 = ADCH;
+        uint16_t val = low_11 + (high_11 << 8);
+
+        if (n >= 4)
+        {
+            sum += val;
+            num++;
+        }
+    }
+    ADCSRA = 0;
+    PRR |= _BV(PRADC);
+
+    //float res_volts = 1.1 * 1024 * num / sum;
+    //return 1000 * res_volts;
+    return ((uint32_t)1100*1024*num) / sum;
+}
+
+static void
+do_fridge()
+{
+    struct epoch_ticks now;
+    get_epoch_ticks(&now);
+    uint32_t off_time = now.ticks - fridge_off_clock.ticks;
+    bool wort_valid = last_wort != DS18X20_INVALID_DECICELSIUS;
+    bool fridge_valid = last_fridge != DS18X20_INVALID_DECICELSIUS;
+
+    int16_t wort_max = fridge_setpoint + fridge_difference;
+    int16_t wort_min = fridge_setpoint;
+
+    // the fridge min/max only apply if the wort sensor is broken
+    int16_t fridge_min = fridge_setpoint - FRIDGE_AIR_MIN_RANGE;
+    int16_t fridge_max = fridge_setpoint + FRIDGE_AIR_MAX_RANGE;
+
+    uint8_t fridge_on = PORT_FRIDGE & _BV(PIN_FRIDGE);
+    printf_P(PSTR("last_wort %hd (%hd, %hd), last_fridge %hd (%hd, %hd), setpoint %hd, diff %hd, fridge_on %hhu\n"), 
+            last_wort, wort_min, wort_max, 
+            last_fridge, fridge_min, fridge_max, 
+            fridge_setpoint, fridge_difference, fridge_on);
+
+    if (off_time < fridge_delay)
+    {
+        printf_P(PSTR("waiting for fridge delay current %hu, wait %hu\n"),
+                off_time, fridge_delay);
+        return;
+    }
+
+    // handle failure of the wort sensor. if it is a short (intermittent?)
+    // failure we wait until it has been broken for a period of time
+    // (WORT_INVALID_TIME) before doing anything.
+    if (wort_valid)
+    {
+        wort_valid_clock = now;
+    }
+    else
+    {
+        printf_P(PSTR("wort sensor is invalid\n"));
+        uint32_t invalid_time = now.ticks - wort_valid_clock.ticks;
+        if (invalid_time < WORT_INVALID_TIME)
+        {
+            printf("only been invalid for %ld, waiting\n", invalid_time);
+            return;
+        }
+    }
+
+    if (!fridge_valid)
+    {
+        printf_P(PSTR("fridge sensor is invalid\n"));
+    }
+
+    if (fridge_on)
+    {
+        bool turn_off = false;
+        uint16_t on_time = now.ticks - fridge_on_clock.ticks;
+
+        uint16_t overshoot = 0;
+        if (on_time > overshoot_delay)
+        {
+            overshoot = overshoot_factor * MIN(OVERSHOOT_MAX_DIV, on_time) / OVERSHOOT_MAX_DIV;
+        }
+
+        printf_P(PSTR("on_time %hu, overshoot %hu\n"), on_time, overshoot);
+
+        // wort has cooled enough. will probably cool a bit more by itself
+        if (wort_valid)
+        {
+            if ((last_wort - overshoot) < fridge_setpoint)
+            {
+                printf_P(PSTR("wort has cooled enough, overshoot %hu on_time %hu\n"), overshoot, on_time);
+                turn_off = true;
+            }
+        }
+        else
+        {
+            if (fridge_valid && last_fridge < fridge_min)
+            {
+                printf_P(PSTR("fridge off fallback\n"));
+                turn_off = true;
+            }
+        }
+
+        if (turn_off)
+        {
+            // too cold, turn off
+            printf_P(PSTR("Turning fridge off\n"));
+            PORT_FRIDGE &= ~_BV(PIN_FRIDGE);
+            fridge_off_clock = now;
+        }
+    }
+    else
+    {
+        bool turn_on = false;
+
+        if (wort_valid)
+        {
+            if (last_wort >= wort_max)
+            {
+                printf_P(PSTR("wort is too hot\n"));
+                turn_on = true;
+            }
+        }
+        else
+        {
+            if (fridge_valid && last_fridge >= fridge_max)
+            {
+                printf_P(PSTR("fridge on fallback\n"));
+                turn_on = true;
+            }
+        }
+
+        if (turn_on)
+        {
+            // too hot, turn on
+            printf_P(PSTR("Turning fridge on\n"));
+            PORT_FRIDGE |= _BV(PIN_FRIDGE);
+            fridge_on_clock = now;
+        }
+    }
+}
+
+static void
+do_measurement()
+{
+    blink();
+
+    /* Take the timer here since deep_sleep() below could take 6 seconds */
+    get_epoch_ticks(&last_measurement_clock);
+    if (n_measurements == 0)
+    {
+        first_measurement_clock = last_measurement_clock;
+    }
+
+    simple_ds18b20_start_meas(NULL);
+    _delay_ms(DS18B20_TCONV_12BIT);
+
+    if (n_measurements == max_measurements)
+    {
+        n_measurements = 0;
+    }
+
+    for (uint8_t s = 0; s < n_sensors; s++)
+    {
+        uint16_t reading;
+        uint8_t ret = simple_ds18b20_read_raw(sensor_id[s], &reading);
+        if (ret != DS18X20_OK)
+        {
+            reading = VALUE_BROKEN;
+        }
+        set_measurement(s, n_measurements, reading);
+
+        if (memcmp(sensor_id[s], fridge_id, sizeof(fridge_id)) == 0)
+        {
+            last_fridge = ds18b20_raw16_to_decicelsius(reading);
+        }
+        if (memcmp(sensor_id[s], wort_id, sizeof(wort_id)) == 0)
+        {
+            last_wort = ds18b20_raw16_to_decicelsius(reading);
+        }
+    }
+
+    n_measurements++;
+}
+
+static void
+do_comms()
+{
+    get_epoch_ticks(&last_comms_clock);
+
+    // turn on bluetooth
+    set_aux_power(1);
+    // avoid receiving rubbish, perhaps
+    _delay_ms(50);
+    uart_on();
+    
+    // write sd card here? same 3.3v regulator...
+    
+    for (comms_timeout = wake_secs; 
+        comms_timeout > 0 || stay_awake;  
+        )
+    {
+        if (need_measurement)
+        {
+            need_measurement = 0;
+            do_measurement();
+            do_fridge();
+            continue;
+        }
+
+        if (have_cmd)
+        {
+            have_cmd = 0;
+            read_handler();
+            continue;
+        }
+
+        // wait for commands from the master
+        idle_sleep();
+    }
+
+    uart_off();
+    // in case bluetooth takes time to flush
+    _delay_ms(100);
+    set_aux_power(0);
+}
+
+static void
+blink()
+{
+    PORT_LED &= ~_BV(PIN_LED);
+    _delay_ms(1);
+    PORT_LED |= _BV(PIN_LED);
+}
+
+static void
+long_delay(int ms)
+{
+    int iter = ms / 100;
+
+    for (int i = 0; i < iter; i++)
+    {
+        _delay_ms(100);
+    }
+}
+
+ISR(BADISR_vect)
+{
+    //uart_on();
+    printf_P(PSTR("Bad interrupt\n"));
+}
+
+int main(void)
+{
+    setup_chip();
+    blink();
+
+    set_aux_power(0);
+
+    stdout = &mystdout;
+    uart_on();
+
+    printf(PSTR("Started.\n"));
+
+    load_params();
+
+    init_sensors();
+
+    uart_off();
+
+    // turn off everything except timer2
+    PRR = _BV(PRTWI) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC);
+
+    setup_tick_counter();
+
+    sei();
+
+    need_comms = 1;
+    need_measurement = 1;
+
+    stay_awake = 1;
+
+    for(;;)
+    {
+        if (button_pressed)
+        {
+            // debounce
+            _delay_ms(200);
+            need_comms = 1;
+            comms_timeout = wake_secs;
+            button_pressed = 0;
+            continue;
+        }
+
+        if (need_comms)
+        {
+            need_comms = 0;
+            do_comms();
+            continue;
+        }
+
+        if (need_measurement)
+        {
+            need_measurement = 0;
+            do_measurement();
+            do_fridge();
+            continue;
+        }
+
+        deep_sleep();
+    }
+
+    return 0;   /* never reached */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/onewire.c	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,287 @@
+/* 
+Access Dallas 1-Wire Devices with ATMEL AVRs
+Author of the initial code: Peter Dannegger (danni(at)specs.de)
+modified by Martin Thomas (mthomas(at)rhrk.uni-kl.de)
+ 9/2004 - use of delay.h, optional bus configuration at runtime
+10/2009 - additional delay in ow_bit_io for recovery
+ 5/2010 - timing modifcations, additonal config-values and comments,
+          use of atomic.h macros, internal pull-up support
+ 7/2010 - added method to skip recovery time after last bit transfered
+          via ow_command_skip_last_recovery
+*/
+
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include <util/atomic.h>
+
+#include "onewire.h"
+
+#ifdef OW_ONE_BUS
+
+#define OW_GET_IN()   ( OW_IN & (1<<OW_PIN))
+#define OW_OUT_LOW()  ( OW_OUT &= (~(1 << OW_PIN)) )
+#define OW_OUT_HIGH() ( OW_OUT |= (1 << OW_PIN) )
+#define OW_DIR_IN()   ( OW_DDR &= (~(1 << OW_PIN )) )
+#define OW_DIR_OUT()  ( OW_DDR |= (1 << OW_PIN) )
+
+#else
+
+/* set bus-config with ow_set_bus() */
+uint8_t OW_PIN_MASK; 
+volatile uint8_t* OW_IN;
+volatile uint8_t* OW_OUT;
+volatile uint8_t* OW_DDR;
+
+#define OW_GET_IN()   ( *OW_IN & OW_PIN_MASK )
+#define OW_OUT_LOW()  ( *OW_OUT &= (uint8_t) ~OW_PIN_MASK )
+#define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t)  OW_PIN_MASK )
+#define OW_DIR_IN()   ( *OW_DDR &= (uint8_t) ~OW_PIN_MASK )
+#define OW_DIR_OUT()  ( *OW_DDR |= (uint8_t)  OW_PIN_MASK )
+
+void ow_set_bus(volatile uint8_t* in,
+	volatile uint8_t* out,
+	volatile uint8_t* ddr,
+	uint8_t pin)
+{
+	OW_DDR=ddr;
+	OW_OUT=out;
+	OW_IN=in;
+	OW_PIN_MASK = (1 << pin);
+	ow_reset();
+}
+
+#endif
+
+uint8_t ow_input_pin_state()
+{
+	return OW_GET_IN();
+}
+
+void ow_parasite_enable(void)
+{
+	OW_OUT_HIGH();
+	OW_DIR_OUT();
+}
+
+void ow_parasite_disable(void)
+{
+	OW_DIR_IN();
+#if (!OW_USE_INTERNAL_PULLUP)
+	OW_OUT_LOW();
+#endif
+}
+
+
+uint8_t ow_reset(void)
+{
+	uint8_t err;
+	
+	OW_OUT_LOW();
+	OW_DIR_OUT();            // pull OW-Pin low for 480us
+	_delay_us(480);
+
+	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+		// set Pin as input - wait for clients to pull low
+		OW_DIR_IN(); // input
+#if OW_USE_INTERNAL_PULLUP
+		OW_OUT_HIGH();
+#endif
+	
+		_delay_us(64);       // was 66
+		err = OW_GET_IN();   // no presence detect
+		                     // if err!=0: nobody pulled to low, still high
+	}
+	
+	// after a delay the clients should release the line
+	// and input-pin gets back to high by pull-up-resistor
+	_delay_us(480 - 64);       // was 480-66
+	if( OW_GET_IN() == 0 ) {
+		err = 1;             // short circuit, expected low but got high
+	}
+	
+	return err;
+}
+
+
+/* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
+   The master should sample at the end of the 15-slot after initiating
+   the read-time-slot. The variable bus-settings need more
+   cycles than the constant ones so the delays had to be shortened 
+   to achive a 15uS overall delay 
+   Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
+   but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
+static uint8_t ow_bit_io_intern( uint8_t b, uint8_t with_parasite_enable )
+{
+	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+#if OW_USE_INTERNAL_PULLUP
+		OW_OUT_LOW();
+#endif
+		OW_DIR_OUT();    // drive bus low
+		_delay_us(2);    // T_INT > 1usec accoding to timing-diagramm
+		if ( b ) {
+			OW_DIR_IN(); // to write "1" release bus, resistor pulls high
+#if OW_USE_INTERNAL_PULLUP
+			OW_OUT_HIGH();
+#endif
+		}
+
+		// "Output data from the DS18B20 is valid for 15usec after the falling
+		// edge that initiated the read time slot. Therefore, the master must 
+		// release the bus and then sample the bus state within 15ussec from 
+		// the start of the slot."
+		_delay_us(15-2-OW_CONF_DELAYOFFSET);
+		
+		if( OW_GET_IN() == 0 ) {
+			b = 0;  // sample at end of read-timeslot
+		}
+	
+		_delay_us(60-15-2+OW_CONF_DELAYOFFSET);
+#if OW_USE_INTERNAL_PULLUP
+		OW_OUT_HIGH();
+#endif
+		OW_DIR_IN();
+	
+		if ( with_parasite_enable ) {
+			ow_parasite_enable();
+		}
+	
+	} /* ATOMIC_BLOCK */
+
+	_delay_us(OW_RECOVERY_TIME); // may be increased for longer wires
+
+	return b;
+}
+
+uint8_t ow_bit_io( uint8_t b )
+{
+	return ow_bit_io_intern( b & 1, 0 );
+}
+
+uint8_t ow_byte_wr( uint8_t b )
+{
+	uint8_t i = 8, j;
+	
+	do {
+		j = ow_bit_io( b & 1 );
+		b >>= 1;
+		if( j ) {
+			b |= 0x80;
+		}
+	} while( --i );
+	
+	return b;
+}
+
+uint8_t ow_byte_wr_with_parasite_enable( uint8_t b )
+{
+	uint8_t i = 8, j;
+	
+	do {
+		if ( i != 1 ) {
+			j = ow_bit_io_intern( b & 1, 0 );
+		} else {
+			j = ow_bit_io_intern( b & 1, 1 );
+		}
+		b >>= 1;
+		if( j ) {
+			b |= 0x80;
+		}
+	} while( --i );
+	
+	return b;
+}
+
+
+uint8_t ow_byte_rd( void )
+{
+	// read by sending only "1"s, so bus gets released
+	// after the init low-pulse in every slot
+	return ow_byte_wr( 0xFF ); 
+}
+
+
+uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
+{
+	uint8_t i, j, next_diff;
+	uint8_t b;
+	
+	if( ow_reset() ) {
+		return OW_PRESENCE_ERR;         // error, no device found <--- early exit!
+	}
+	
+	ow_byte_wr( OW_SEARCH_ROM );        // ROM search command
+	next_diff = OW_LAST_DEVICE;         // unchanged on last device
+	
+	i = OW_ROMCODE_SIZE * 8;            // 8 bytes
+	
+	do {
+		j = 8;                          // 8 bits
+		do {
+			b = ow_bit_io( 1 );         // read bit
+			if( ow_bit_io( 1 ) ) {      // read complement bit
+				if( b ) {               // 0b11
+					return OW_DATA_ERR; // data error <--- early exit!
+				}
+			}
+			else {
+				if( !b ) {              // 0b00 = 2 devices
+					if( diff > i || ((*id & 1) && diff != i) ) {
+						b = 1;          // now 1
+						next_diff = i;  // next pass 0
+					}
+				}
+			}
+			ow_bit_io( b );             // write bit
+			*id >>= 1;
+			if( b ) {
+				*id |= 0x80;            // store bit
+			}
+			
+			i--;
+			
+		} while( --j );
+		
+		id++;                           // next byte
+	
+	} while( i );
+	
+	return next_diff;                   // to continue search
+}
+
+
+static void ow_command_intern( uint8_t command, uint8_t *id, uint8_t with_parasite_enable )
+{
+	uint8_t i;
+
+	ow_reset();
+
+	if( id ) {
+		ow_byte_wr( OW_MATCH_ROM );     // to a single device
+		i = OW_ROMCODE_SIZE;
+		do {
+			ow_byte_wr( *id );
+			id++;
+		} while( --i );
+	} 
+	else {
+		ow_byte_wr( OW_SKIP_ROM );      // to all devices
+	}
+	
+	if ( with_parasite_enable  ) {
+		ow_byte_wr_with_parasite_enable( command );
+	} else {
+		ow_byte_wr( command );
+	}
+}
+
+void ow_command( uint8_t command, uint8_t *id )
+{
+	ow_command_intern( command, id, 0);
+}
+
+void ow_command_with_parasite_enable( uint8_t command, uint8_t *id )
+{
+	ow_command_intern( command, id, 1 );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/onewire.h	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,93 @@
+#ifndef ONEWIRE_H_
+#define ONEWIRE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/*******************************************/
+/* Hardware connection                     */
+/*******************************************/
+
+/* Define OW_ONE_BUS if only one 1-Wire-Bus is used
+   in the application -> shorter code.
+   If not defined make sure to call ow_set_bus() before using 
+   a bus. Runtime bus-select increases code size by around 300 
+   bytes so use OW_ONE_BUS if possible */
+#define OW_ONE_BUS
+
+#ifdef OW_ONE_BUS
+
+#define OW_PIN  PB1
+#define OW_IN   PINB
+#define OW_OUT  PORTB
+#define OW_DDR  DDRB
+#define OW_CONF_DELAYOFFSET 0
+
+#else 
+#if ( F_CPU < 1843200 )
+#warning | Experimental multi-bus-mode is not tested for 
+#warning | frequencies below 1,84MHz. Use OW_ONE_WIRE or
+#warning | faster clock-source (i.e. internal 2MHz R/C-Osc.).
+#endif
+#define OW_CONF_CYCLESPERACCESS 13
+#define OW_CONF_DELAYOFFSET ( (uint16_t)( ((OW_CONF_CYCLESPERACCESS) * 1000000L) / F_CPU ) )
+#endif
+
+// Recovery time (T_Rec) minimum 1usec - increase for long lines 
+// 5 usecs is a value give in some Maxim AppNotes
+// 30u secs seem to be reliable for longer lines
+//#define OW_RECOVERY_TIME        5  /* usec */
+//#define OW_RECOVERY_TIME      300 /* usec */
+#define OW_RECOVERY_TIME         10 /* usec */
+
+// Use AVR's internal pull-up resistor instead of external 4,7k resistor.
+// Based on information from Sascha Schade. Experimental but worked in tests
+// with one DS18B20 and one DS18S20 on a rather short bus (60cm), where both 
+// sensores have been parasite-powered.
+#define OW_USE_INTERNAL_PULLUP     1  /* 0=external, 1=internal */
+
+/*******************************************/
+
+
+#define OW_MATCH_ROM    0x55
+#define OW_SKIP_ROM     0xCC
+#define OW_SEARCH_ROM   0xF0
+
+#define OW_SEARCH_FIRST 0xFF        // start new search
+#define OW_PRESENCE_ERR 0xFF
+#define OW_DATA_ERR     0xFE
+#define OW_LAST_DEVICE  0x00        // last device found
+
+// rom-code size including CRC
+#define OW_ROMCODE_SIZE 8
+
+extern uint8_t ow_reset(void);
+
+extern uint8_t ow_bit_io( uint8_t b );
+extern uint8_t ow_byte_wr( uint8_t b );
+extern uint8_t ow_byte_rd( void );
+
+extern uint8_t ow_rom_search( uint8_t diff, uint8_t *id );
+
+extern void ow_command( uint8_t command, uint8_t *id );
+extern void ow_command_with_parasite_enable( uint8_t command, uint8_t *id );
+
+extern void ow_parasite_enable( void );
+extern void ow_parasite_disable( void );
+extern uint8_t ow_input_pin_state( void );
+
+#ifndef OW_ONE_BUS
+extern void ow_set_bus( volatile uint8_t* in,
+	volatile uint8_t* out,
+	volatile uint8_t* ddr,
+	uint8_t pin );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/server/config.py	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,1 @@
+../web/config.py
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/server/dump.py	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,190 @@
+#!/usr/bin/env python2.7
+
+BTADDR = "00:12:03:27:70:88"
+SLEEP_TIME = 5
+# time that the bluetooth takes to get going?
+EXTRA_WAKEUP = 0
+
+FETCH_TRIES = 3
+
+# avoid turning off the bluetooth etc.
+TESTING = False
+
+import sys
+# for wrt
+sys.path.append('/root/python')
+import httplib
+import time
+import traceback
+import binascii
+import hmac
+import zlib
+import urllib
+import urllib2
+
+import config
+
+from utils import monotonic_time, retry, readline, crc16
+
+lightblue = None
+try:
+    import lightblue
+except ImportError:
+    import bluetooth
+
+def get_socket(addr):
+    if lightblue:
+        s = lightblue.socket()
+        s.connect((addr, 1))
+        s.settimeout(3)
+    else:
+        s = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
+        s.connect((addr, 1))
+
+    s.setblocking(False)
+
+    return s
+
+
+@retry()
+def fetch(sock):
+    print "fetch"
+    sock.send("fetch\n")
+
+    crc = 0
+
+    lines = []
+    l = readline(sock)
+    if l != 'START\n':
+        print>>sys.stderr, "Bad expected START line '%s'\n" % l.rstrip('\n')
+        return None
+    crc = crc16(l, crc)
+
+    while True:
+        l = readline(sock)
+
+        crc = crc16(l, crc)
+
+        if l == 'END\n':
+            break
+
+        lines.append(l.rstrip('\n'))
+
+    print lines
+
+    l = readline(sock)
+    recv_crc = None
+    try:
+        k, v = l.rstrip('\n').split('=')
+        print k,v
+        if k == 'CRC':
+            recv_crc = int(v)
+        if recv_crc < 0 or recv_crc > 0xffff:
+            recv_crc = None
+    except ValueError:
+        pass
+
+    if recv_crc is None:
+        print>>sys.stderr, "Bad expected CRC line '%s'\n" % l.rstrip('\n')
+        return None
+
+    if recv_crc != crc:
+        print>>sys.stderr, "Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc)
+        return None
+
+    return lines
+
+@retry()
+def turn_off(sock):
+    if TESTING:
+        return 99
+    print>>sys.stderr, "sending btoff"
+    sock.send("btoff\n");
+    # read newline
+    l = readline(sock)
+    if not l:
+        print>>sys.stderr, "Bad response to btoff\n"
+        return None
+
+    if not l.startswith('off:'):
+        print>>sys.stderr, "Bad response to btoff '%s'\n" % l
+        return None
+    off, next_wake = l.rstrip().split(':')
+    print>>sys.stderr, "Next wake %s" % next_wake
+
+    return int(next_wake)
+
+@retry()
+def clear_meas(sock):
+    sock.send("clear\n");
+    l = readline(sock)
+    if l and l.rstrip() == 'cleared':
+        return True
+
+    print>>sys.stderr, "Bad response to clear %s\n" % str(l)
+    return False
+
+def send_results(lines):
+    enc_lines = binascii.b2a_base64(zlib.compress('\n'.join(lines)))
+    mac = hmac.new(config.HMAC_KEY, enc_lines).hexdigest()
+
+    url_data = urllib.urlencode( {'lines': enc_lines, 'hmac': mac} )
+    con = urllib2.urlopen(config.UPDATE_URL, url_data)
+    result = con.read(100)
+    if result == 'OK':
+        return True
+    else:
+        print>>sys.stderr, "Bad result '%s'" % result
+        return False
+
+def do_comms(sock):
+    args = sys.argv[1:]
+    print "do_comms"
+    for a in args:
+        sock.send('%s\n' % a)
+
+    while True:
+        l = readline(sock)
+	if not l:
+		print '.',
+		sys.stdout.flush()
+	else:
+		print l
+
+testcount = 0
+
+def sleep_for(secs):
+    until = monotonic_time() + secs
+    while True:
+        length = until - monotonic_time()
+        if length <= 0:
+            return
+        time.sleep(length)
+
+def main():
+    next_wake_time = 0
+
+    while True:
+        sock = None
+        try:
+            sock = get_socket(BTADDR)
+        except Exception, e:
+            print>>sys.stderr, "Error connecting:"
+            traceback.print_exc(file=sys.stderr)
+        sleep_time = SLEEP_TIME
+        if sock:
+            next_wake = None
+            try:
+                next_wake_interval = do_comms(sock)
+                next_wake_time = time.time() + next_wake_interval
+            except Exception, e:
+                print>>sys.stderr, "Error in do_comms:"
+                traceback.print_exc(file=sys.stderr)
+            if next_wake_time > time.time():
+                sleep_time = min(next_wake_time - time.time() - EXTRA_WAKEUP, sleep_time)
+
+        print "Sleeping for %d" % sleep_time
+        sleep_for(sleep_time)
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/server/ts.py	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,239 @@
+#!/usr/bin/env python2.7
+
+# time that the bluetooth takes to get going?
+EXTRA_WAKEUP = -3
+
+FETCH_TRIES = 3
+
+# avoid turning off the bluetooth etc.
+TESTING = False
+
+import sys
+# for wrt
+sys.path.append('/root/python')
+import httplib
+import time
+import traceback
+import binascii
+import hmac
+import zlib
+import urllib
+import urllib2
+import logging
+import socket
+
+L = logging.info
+W = logging.warning
+E = logging.error
+
+import config
+
+from utils import monotonic_time, retry, readline, crc16
+import utils
+
+import bluetooth
+
+def get_socket(addr):
+    s = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
+    L("connecting")
+    s.connect((addr, 1))
+    s.setblocking(False)
+    s.settimeout(1)
+            
+    return s
+
+
+def flush(sock):
+    ret = []
+    while True:
+        l = readline(sock)
+        if l:
+            ret.append(l)
+        else:
+            break
+    return ret
+
+def encode_extra(extra_lines):
+    return ['extra%d=%s' % (n, l.strip()) for (n,l) in enumerate(extra_lines)]
+
+@retry()
+def fetch(sock):
+    extra_lines = flush(sock)
+    sock.send("fetch\n")
+
+    crc = 0
+
+    lines = []
+    l = readline(sock)
+    if not l:
+        return None
+
+    if l != 'START\n':
+        W("Bad expected START line '%s'\n" % l.rstrip('\n'))
+        extra_lines.append(l)
+        return encode_extra(extra_lines)
+    crc = crc16(l, crc)
+
+    while True:
+        l = readline(sock)
+
+        crc = crc16(l, crc)
+
+        if l == 'END\n':
+            break
+
+        lines.append(l.rstrip('\n'))
+
+    lines += encode_extra(extra_lines)
+
+    for d in lines:
+        L("Received: %s" % d)
+        
+    l = readline(sock)
+    recv_crc = None
+    try:
+        k, v = l.rstrip('\n').split('=')
+        if k == 'CRC':
+            recv_crc = int(v)
+        if recv_crc < 0 or recv_crc > 0xffff:
+            recv_crc = None
+    except ValueError:
+        pass
+
+    if recv_crc is None:
+        W("Bad expected CRC line '%s'\n" % l.rstrip('\n'))
+        return None
+
+    if recv_crc != crc:
+        W("Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc))
+        return None
+
+    return lines
+
+@retry()
+def turn_off(sock):
+    if TESTING:
+        return 99
+    L("Sending btoff")
+    flush(sock)
+    sock.send("btoff\n");
+    # read newline
+    l = readline(sock)
+    if not l:
+        W("Bad response to btoff")
+        return None
+
+    if not l.startswith('next_wake'):
+        W("Bad response to btoff '%s'" % l)
+        return None
+    L("Next wake line %s" % l)
+
+    toks = dict(v.split('=') for v in l.split(','))
+
+    rem = int(toks['rem'])
+    tick_secs = int(toks['tick_secs'])
+    tick_wake = int(toks['tick_wake']) + 1
+    next_wake = int(toks['next_wake'])
+
+    rem_secs = float(rem) / tick_wake * tick_secs
+
+    next_wake_secs = next_wake - rem_secs
+    L("next_wake_secs %f\n", next_wake_secs)
+    return next_wake_secs
+
+@retry()
+def clear_meas(sock):
+    flush(sock)
+    sock.send("clear\n");
+    l = readline(sock)
+    if l and l.rstrip() == 'cleared':
+        return True
+
+    E("Bad response to clear '%s'" % str(l))
+    return False
+
+def send_results(lines):
+    enc_lines = binascii.b2a_base64(zlib.compress('\n'.join(lines)))
+    mac = hmac.new(config.HMAC_KEY, enc_lines).hexdigest()
+
+    url_data = urllib.urlencode( {'lines': enc_lines, 'hmac': mac} )
+    con = urllib2.urlopen(config.UPDATE_URL, url_data)
+    result = con.read(100)
+    if result == 'OK':
+        return True
+    else:
+        W("Bad result '%s'" % result)
+        return False
+
+def do_comms(sock):
+    L("do_comms")
+    d = None
+    # serial could be unreliable, try a few times
+    d = fetch(sock)
+    if not d:
+        return
+
+    res = send_results(d)
+    if not res:
+        return
+
+    clear_meas(sock)
+
+    next_wake = 600
+    #next_wake = turn_off(sock)
+    #sock.close()
+    return next_wake
+
+testcount = 0
+
+def sleep_for(secs):
+    until = monotonic_time() + secs
+    while True:
+        length = until - monotonic_time()
+        if length <= 0:
+            return
+        time.sleep(length)
+
+def setup_logging():
+    logging.basicConfig(format='%(asctime)s %(message)s', 
+            datefmt='%m/%d/%Y %I:%M:%S %p',
+            level=logging.INFO)
+
+def get_net_socket(host, port):
+    s = socket.create_connection((host, port))
+    s.setblocking(False)
+    s.settimeout(1)
+    return s
+
+def main():
+    setup_logging()
+
+    L("Running templog rfcomm server")
+
+    if '--daemon' in sys.argv:
+        utils.cheap_daemon()
+
+    next_wake_time = 0
+
+    while True:
+        sock = None
+        try:
+            sock = get_net_socket(config.SERIAL_HOST, config.SERIAL_PORT)
+        except Exception, e:
+            #logging.exception("Error connecting")
+            pass
+
+        if not sock:
+            sleep_for(config.SLEEP_TIME)
+            continue
+
+        while True:
+            try:
+                do_comms(sock)
+                sleep_for(config.SLEEP_TIME)
+            except Exception, e:
+                logging.exception("Error in do_comms")
+                break
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/server/utils.py	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,127 @@
+import os
+import sys
+#import ctypes
+import time
+import select
+import logging
+
+L = logging.info
+W = logging.warning
+E = logging.error
+
+DEFAULT_TRIES = 3
+READLINE_SELECT_TIMEOUT = 1
+
+__all__ = ('monotonic_time', 'retry')
+
+clock_gettime = None
+no_clock_gettime = True
+def monotonic_time():
+    global clock_gettime
+    global no_clock_gettime
+    if no_clock_gettime:
+        return time.time()
+
+    class timespec(ctypes.Structure):
+        _fields_ = [
+            ('tv_sec', ctypes.c_long),
+            ('tv_nsec', ctypes.c_long)
+        ]
+    if not clock_gettime:
+        try:
+            librt = ctypes.CDLL('librt.so.0', use_errno=True)
+            clock_gettime = librt.clock_gettime
+            clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
+        except:
+            W("No clock_gettime(), using fake fallback.")
+            no_clock_gettime = True
+            return time.time()
+        
+    t = timespec()
+    CLOCK_MONOTONIC = 1 # see <linux/time.h>
+
+    if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
+        errno_ = ctypes.get_errno()
+        raise OSError(errno_, os.strerror(errno_))
+    return t.tv_sec + t.tv_nsec * 1e-9
+
+# decorator, tries a number of times, returns None on failure, sleeps between
+# Must be used as "@retry()" if arguments are defaulted
+def retry(retries=DEFAULT_TRIES, try_time = 1):
+    def inner(func):
+        def new_f(*args, **kwargs):
+            for i in range(retries):
+                d = func(*args, **kwargs)
+                if d is not None:
+                    return d
+                time.sleep(try_time)
+            return None
+
+        new_f.func_name = func.func_name
+        return new_f
+    return inner
+
+def readline(sock):
+    timeout = READLINE_SELECT_TIMEOUT
+    buf = ''
+    while True:
+        (rlist, wlist, xlist) = select.select([sock], [], [], timeout)
+        if sock not in rlist:
+            # hit timeout
+            return None
+
+        c = sock.recv(1)
+        if c == '':
+            # lightblue timeout
+            return None
+        if c == '\r':
+            continue
+
+        buf += c
+        if c == '\n':
+            return buf
+
+# from http://blog.stalkr.net/2011/04/pctf-2011-32-thats-no-bluetooth.html
+def crc16(buff, crc = 0, poly = 0x8408):
+    l = len(buff)
+    i = 0
+    while i < l:
+        ch = ord(buff[i])
+        uc = 0
+        while uc < 8:
+            if (crc & 1) ^ (ch & 1):
+                crc = (crc >> 1) ^ poly
+            else:
+                crc >>= 1
+            ch >>= 1
+            uc += 1
+        i += 1
+    return crc
+
+def cheap_daemon():
+    L("Daemonising.")
+    sys.stdout.flush()
+    sys.stderr.flush()
+    out = file('/dev/null', 'a+')
+    os.dup2(out.fileno(), sys.stdout.fileno())
+    os.dup2(out.fileno(), sys.stderr.fileno())
+
+    try:
+        pid = os.fork()
+        if pid > 0:
+            sys.exit(0)
+    except OSError, e:
+        E("Bad fork()")
+        sys.exit(1)
+
+    os.setsid()
+
+    try:
+        pid = os.fork()
+        if pid > 0:
+            sys.exit(0)
+    except OSError, e:
+        E("Bad fork()")
+        sys.exit(1)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/simple_ds18b20.c	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,192 @@
+// Matt Johnston 2012
+// Based on ds18x20.c by Martin Thomas, in turn based on code by 
+// Peter // Dannegger and others.
+//
+#include <stdio.h>
+#include <avr/pgmspace.h>
+
+#include "ds18x20.h"
+#include "onewire.h"
+#include "crc8.h"
+
+#include "simple_ds18b20.h"
+
+uint8_t 
+simple_ds18b20_start_meas(uint8_t id[])
+{
+	uint8_t ret;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		ow_command_with_parasite_enable(DS18X20_CONVERT_T, id);
+		ret = DS18X20_OK;
+	} 
+	else { 
+		ret = DS18X20_START_FAIL;
+	}
+
+	return ret;
+}
+
+static uint8_t 
+read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
+{
+	uint8_t i;
+	uint8_t ret;
+
+	ow_command( DS18X20_READ, id );
+	for ( i = 0; i < n; i++ ) {
+		sp[i] = ow_byte_rd();
+	}
+	if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
+		ret = DS18X20_ERROR_CRC;
+	} else {
+		ret = DS18X20_OK;
+	}
+
+	return ret;
+}
+
+int16_t 
+ds18b20_raw16_to_decicelsius(uint16_t measure)
+{
+	uint8_t  negative;
+	int16_t  decicelsius;
+	uint16_t fract;
+
+	// check for negative 
+	if ( measure & 0x8000 )  {
+		negative = 1;       // mark negative
+		measure ^= 0xffff;  // convert to positive => (twos complement)++
+		measure++;
+	}
+	else {
+		negative = 0;
+	}
+
+	decicelsius = (measure >> 4);
+	decicelsius *= 10;
+
+	// decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
+	// 625/1000 = 640/1024
+	fract = ( measure & 0x000F ) * 640;
+	if ( !negative ) {
+		fract += 512;
+	}
+	fract /= 1024;
+	decicelsius += fract;
+
+	if ( negative ) {
+		decicelsius = -decicelsius;
+	}
+
+	if ( decicelsius == 850 || decicelsius < -550 || decicelsius > 1250 ) {
+		return DS18X20_INVALID_DECICELSIUS;
+	} else {
+		return decicelsius;
+	}
+}
+
+uint8_t 
+simple_ds18b20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
+{
+    uint16_t reading;
+	uint8_t ret;
+
+    ret = simple_ds18b20_read_raw(id, &reading);
+    if (ret == DS18X20_OK)
+    {
+        *decicelsius = ds18b20_raw16_to_decicelsius(reading);
+    }
+    return ret;
+}
+
+uint8_t 
+simple_ds18b20_read_raw( uint8_t id[], uint16_t *reading )
+{
+	uint8_t sp[DS18X20_SP_SIZE];
+	uint8_t ret;
+	
+	if (id)
+	{
+		ow_reset();
+	}
+	ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
+	if ( ret == DS18X20_OK ) {
+        *reading = sp[0] | (sp[1] << 8);
+	}
+	return ret;
+}
+
+static void 
+printhex_nibble(const unsigned char b, FILE *stream)
+{
+	unsigned char  c = b & 0x0f;
+	if ( c > 9 ) { 
+		c += 'A'-10; 
+	}
+	else {
+		c += '0';
+	}
+	fputc(c, stream);
+}
+
+void 
+printhex_byte(const unsigned char b, FILE *stream)
+{
+	printhex_nibble( b >> 4, stream);
+	printhex_nibble( b, stream);
+}
+
+void
+printhex(uint8_t *id, uint8_t n, FILE *stream)
+{
+	for (uint8_t i = 0; i < n; i++)
+	{
+		if (i > 0)
+		{
+			fputc(' ', stream);
+		}
+		printhex_byte(id[i], stream);
+	}
+}
+
+
+uint8_t 
+simple_ds18b20_read_all()
+{
+	uint8_t id[OW_ROMCODE_SIZE];
+	for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
+	{
+		diff = ow_rom_search( diff, &id[0] );
+
+		if( diff == OW_PRESENCE_ERR ) {
+			printf_P( PSTR("No Sensor found\r") );
+			return OW_PRESENCE_ERR; // <--- early exit!
+		}
+		
+		if( diff == OW_DATA_ERR ) {
+			printf_P( PSTR("Bus Error\r") );
+			return OW_DATA_ERR;     // <--- early exit!
+		}
+
+		int16_t decicelsius;
+		uint8_t ret = simple_ds18b20_read_decicelsius(NULL, &decicelsius);
+		if (ret != DS18X20_OK)
+		{
+			printf_P(PSTR("Failed reading\r"));
+			return OW_DATA_ERR;
+		}
+
+		printf_P(PSTR("DS18B20 %d: "), diff);
+		if (crc8(id, OW_ROMCODE_SIZE))
+		{
+			printf_P(PSTR("CRC fail"));
+		}
+		printhex(id, OW_ROMCODE_SIZE, stdout);
+		printf_P(PSTR(" %d.%d ºC\n"), decicelsius/10, decicelsius % 10);
+	}
+	printf_P(PSTR("Done sensors\n"));
+	return DS18X20_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/simple_ds18b20.h	Sun Mar 30 20:35:30 2014 +0800
@@ -0,0 +1,16 @@
+#ifndef SIMPLE_DS18B20_H_
+#define SIMPLE_DS18B20_H_
+#include <stdint.h>
+#include <stdio.h>
+
+#include "ds18x20.h"
+
+uint8_t simple_ds18b20_start_meas(uint8_t id[]);
+void printhex(uint8_t *id, uint8_t n, FILE *stream);
+void printhex_byte( const unsigned char  b, FILE *stream );
+uint8_t simple_ds18b20_read_decicelsius( uint8_t id[], int16_t *decicelsius );
+int16_t ds18b20_raw16_to_decicelsius(uint16_t measure);
+uint8_t simple_ds18b20_read_raw( uint8_t id[], uint16_t *reading );
+uint8_t simple_ds18b20_read_all();
+
+#endif // SIMPLE_DS18B20_H_
--- a/onewire.c	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-/* 
-Access Dallas 1-Wire Devices with ATMEL AVRs
-Author of the initial code: Peter Dannegger (danni(at)specs.de)
-modified by Martin Thomas (mthomas(at)rhrk.uni-kl.de)
- 9/2004 - use of delay.h, optional bus configuration at runtime
-10/2009 - additional delay in ow_bit_io for recovery
- 5/2010 - timing modifcations, additonal config-values and comments,
-          use of atomic.h macros, internal pull-up support
- 7/2010 - added method to skip recovery time after last bit transfered
-          via ow_command_skip_last_recovery
-*/
-
-
-#include <avr/io.h>
-#include <util/delay.h>
-#include <util/atomic.h>
-
-#include "onewire.h"
-
-#ifdef OW_ONE_BUS
-
-#define OW_GET_IN()   ( OW_IN & (1<<OW_PIN))
-#define OW_OUT_LOW()  ( OW_OUT &= (~(1 << OW_PIN)) )
-#define OW_OUT_HIGH() ( OW_OUT |= (1 << OW_PIN) )
-#define OW_DIR_IN()   ( OW_DDR &= (~(1 << OW_PIN )) )
-#define OW_DIR_OUT()  ( OW_DDR |= (1 << OW_PIN) )
-
-#else
-
-/* set bus-config with ow_set_bus() */
-uint8_t OW_PIN_MASK; 
-volatile uint8_t* OW_IN;
-volatile uint8_t* OW_OUT;
-volatile uint8_t* OW_DDR;
-
-#define OW_GET_IN()   ( *OW_IN & OW_PIN_MASK )
-#define OW_OUT_LOW()  ( *OW_OUT &= (uint8_t) ~OW_PIN_MASK )
-#define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t)  OW_PIN_MASK )
-#define OW_DIR_IN()   ( *OW_DDR &= (uint8_t) ~OW_PIN_MASK )
-#define OW_DIR_OUT()  ( *OW_DDR |= (uint8_t)  OW_PIN_MASK )
-
-void ow_set_bus(volatile uint8_t* in,
-	volatile uint8_t* out,
-	volatile uint8_t* ddr,
-	uint8_t pin)
-{
-	OW_DDR=ddr;
-	OW_OUT=out;
-	OW_IN=in;
-	OW_PIN_MASK = (1 << pin);
-	ow_reset();
-}
-
-#endif
-
-uint8_t ow_input_pin_state()
-{
-	return OW_GET_IN();
-}
-
-void ow_parasite_enable(void)
-{
-	OW_OUT_HIGH();
-	OW_DIR_OUT();
-}
-
-void ow_parasite_disable(void)
-{
-	OW_DIR_IN();
-#if (!OW_USE_INTERNAL_PULLUP)
-	OW_OUT_LOW();
-#endif
-}
-
-
-uint8_t ow_reset(void)
-{
-	uint8_t err;
-	
-	OW_OUT_LOW();
-	OW_DIR_OUT();            // pull OW-Pin low for 480us
-	_delay_us(480);
-
-	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
-		// set Pin as input - wait for clients to pull low
-		OW_DIR_IN(); // input
-#if OW_USE_INTERNAL_PULLUP
-		OW_OUT_HIGH();
-#endif
-	
-		_delay_us(64);       // was 66
-		err = OW_GET_IN();   // no presence detect
-		                     // if err!=0: nobody pulled to low, still high
-	}
-	
-	// after a delay the clients should release the line
-	// and input-pin gets back to high by pull-up-resistor
-	_delay_us(480 - 64);       // was 480-66
-	if( OW_GET_IN() == 0 ) {
-		err = 1;             // short circuit, expected low but got high
-	}
-	
-	return err;
-}
-
-
-/* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
-   The master should sample at the end of the 15-slot after initiating
-   the read-time-slot. The variable bus-settings need more
-   cycles than the constant ones so the delays had to be shortened 
-   to achive a 15uS overall delay 
-   Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
-   but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
-static uint8_t ow_bit_io_intern( uint8_t b, uint8_t with_parasite_enable )
-{
-	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
-#if OW_USE_INTERNAL_PULLUP
-		OW_OUT_LOW();
-#endif
-		OW_DIR_OUT();    // drive bus low
-		_delay_us(2);    // T_INT > 1usec accoding to timing-diagramm
-		if ( b ) {
-			OW_DIR_IN(); // to write "1" release bus, resistor pulls high
-#if OW_USE_INTERNAL_PULLUP
-			OW_OUT_HIGH();
-#endif
-		}
-
-		// "Output data from the DS18B20 is valid for 15usec after the falling
-		// edge that initiated the read time slot. Therefore, the master must 
-		// release the bus and then sample the bus state within 15ussec from 
-		// the start of the slot."
-		_delay_us(15-2-OW_CONF_DELAYOFFSET);
-		
-		if( OW_GET_IN() == 0 ) {
-			b = 0;  // sample at end of read-timeslot
-		}
-	
-		_delay_us(60-15-2+OW_CONF_DELAYOFFSET);
-#if OW_USE_INTERNAL_PULLUP
-		OW_OUT_HIGH();
-#endif
-		OW_DIR_IN();
-	
-		if ( with_parasite_enable ) {
-			ow_parasite_enable();
-		}
-	
-	} /* ATOMIC_BLOCK */
-
-	_delay_us(OW_RECOVERY_TIME); // may be increased for longer wires
-
-	return b;
-}
-
-uint8_t ow_bit_io( uint8_t b )
-{
-	return ow_bit_io_intern( b & 1, 0 );
-}
-
-uint8_t ow_byte_wr( uint8_t b )
-{
-	uint8_t i = 8, j;
-	
-	do {
-		j = ow_bit_io( b & 1 );
-		b >>= 1;
-		if( j ) {
-			b |= 0x80;
-		}
-	} while( --i );
-	
-	return b;
-}
-
-uint8_t ow_byte_wr_with_parasite_enable( uint8_t b )
-{
-	uint8_t i = 8, j;
-	
-	do {
-		if ( i != 1 ) {
-			j = ow_bit_io_intern( b & 1, 0 );
-		} else {
-			j = ow_bit_io_intern( b & 1, 1 );
-		}
-		b >>= 1;
-		if( j ) {
-			b |= 0x80;
-		}
-	} while( --i );
-	
-	return b;
-}
-
-
-uint8_t ow_byte_rd( void )
-{
-	// read by sending only "1"s, so bus gets released
-	// after the init low-pulse in every slot
-	return ow_byte_wr( 0xFF ); 
-}
-
-
-uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
-{
-	uint8_t i, j, next_diff;
-	uint8_t b;
-	
-	if( ow_reset() ) {
-		return OW_PRESENCE_ERR;         // error, no device found <--- early exit!
-	}
-	
-	ow_byte_wr( OW_SEARCH_ROM );        // ROM search command
-	next_diff = OW_LAST_DEVICE;         // unchanged on last device
-	
-	i = OW_ROMCODE_SIZE * 8;            // 8 bytes
-	
-	do {
-		j = 8;                          // 8 bits
-		do {
-			b = ow_bit_io( 1 );         // read bit
-			if( ow_bit_io( 1 ) ) {      // read complement bit
-				if( b ) {               // 0b11
-					return OW_DATA_ERR; // data error <--- early exit!
-				}
-			}
-			else {
-				if( !b ) {              // 0b00 = 2 devices
-					if( diff > i || ((*id & 1) && diff != i) ) {
-						b = 1;          // now 1
-						next_diff = i;  // next pass 0
-					}
-				}
-			}
-			ow_bit_io( b );             // write bit
-			*id >>= 1;
-			if( b ) {
-				*id |= 0x80;            // store bit
-			}
-			
-			i--;
-			
-		} while( --j );
-		
-		id++;                           // next byte
-	
-	} while( i );
-	
-	return next_diff;                   // to continue search
-}
-
-
-static void ow_command_intern( uint8_t command, uint8_t *id, uint8_t with_parasite_enable )
-{
-	uint8_t i;
-
-	ow_reset();
-
-	if( id ) {
-		ow_byte_wr( OW_MATCH_ROM );     // to a single device
-		i = OW_ROMCODE_SIZE;
-		do {
-			ow_byte_wr( *id );
-			id++;
-		} while( --i );
-	} 
-	else {
-		ow_byte_wr( OW_SKIP_ROM );      // to all devices
-	}
-	
-	if ( with_parasite_enable  ) {
-		ow_byte_wr_with_parasite_enable( command );
-	} else {
-		ow_byte_wr( command );
-	}
-}
-
-void ow_command( uint8_t command, uint8_t *id )
-{
-	ow_command_intern( command, id, 0);
-}
-
-void ow_command_with_parasite_enable( uint8_t command, uint8_t *id )
-{
-	ow_command_intern( command, id, 1 );
-}
-
--- a/onewire.h	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#ifndef ONEWIRE_H_
-#define ONEWIRE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-/*******************************************/
-/* Hardware connection                     */
-/*******************************************/
-
-/* Define OW_ONE_BUS if only one 1-Wire-Bus is used
-   in the application -> shorter code.
-   If not defined make sure to call ow_set_bus() before using 
-   a bus. Runtime bus-select increases code size by around 300 
-   bytes so use OW_ONE_BUS if possible */
-#define OW_ONE_BUS
-
-#ifdef OW_ONE_BUS
-
-#define OW_PIN  PB1
-#define OW_IN   PINB
-#define OW_OUT  PORTB
-#define OW_DDR  DDRB
-#define OW_CONF_DELAYOFFSET 0
-
-#else 
-#if ( F_CPU < 1843200 )
-#warning | Experimental multi-bus-mode is not tested for 
-#warning | frequencies below 1,84MHz. Use OW_ONE_WIRE or
-#warning | faster clock-source (i.e. internal 2MHz R/C-Osc.).
-#endif
-#define OW_CONF_CYCLESPERACCESS 13
-#define OW_CONF_DELAYOFFSET ( (uint16_t)( ((OW_CONF_CYCLESPERACCESS) * 1000000L) / F_CPU ) )
-#endif
-
-// Recovery time (T_Rec) minimum 1usec - increase for long lines 
-// 5 usecs is a value give in some Maxim AppNotes
-// 30u secs seem to be reliable for longer lines
-//#define OW_RECOVERY_TIME        5  /* usec */
-//#define OW_RECOVERY_TIME      300 /* usec */
-#define OW_RECOVERY_TIME         10 /* usec */
-
-// Use AVR's internal pull-up resistor instead of external 4,7k resistor.
-// Based on information from Sascha Schade. Experimental but worked in tests
-// with one DS18B20 and one DS18S20 on a rather short bus (60cm), where both 
-// sensores have been parasite-powered.
-#define OW_USE_INTERNAL_PULLUP     1  /* 0=external, 1=internal */
-
-/*******************************************/
-
-
-#define OW_MATCH_ROM    0x55
-#define OW_SKIP_ROM     0xCC
-#define OW_SEARCH_ROM   0xF0
-
-#define OW_SEARCH_FIRST 0xFF        // start new search
-#define OW_PRESENCE_ERR 0xFF
-#define OW_DATA_ERR     0xFE
-#define OW_LAST_DEVICE  0x00        // last device found
-
-// rom-code size including CRC
-#define OW_ROMCODE_SIZE 8
-
-extern uint8_t ow_reset(void);
-
-extern uint8_t ow_bit_io( uint8_t b );
-extern uint8_t ow_byte_wr( uint8_t b );
-extern uint8_t ow_byte_rd( void );
-
-extern uint8_t ow_rom_search( uint8_t diff, uint8_t *id );
-
-extern void ow_command( uint8_t command, uint8_t *id );
-extern void ow_command_with_parasite_enable( uint8_t command, uint8_t *id );
-
-extern void ow_parasite_enable( void );
-extern void ow_parasite_disable( void );
-extern uint8_t ow_input_pin_state( void );
-
-#ifndef OW_ONE_BUS
-extern void ow_set_bus( volatile uint8_t* in,
-	volatile uint8_t* out,
-	volatile uint8_t* ddr,
-	uint8_t pin );
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
--- a/server/config.py	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../web/config.py
\ No newline at end of file
--- a/server/dump.py	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-#!/usr/bin/env python2.7
-
-BTADDR = "00:12:03:27:70:88"
-SLEEP_TIME = 5
-# time that the bluetooth takes to get going?
-EXTRA_WAKEUP = 0
-
-FETCH_TRIES = 3
-
-# avoid turning off the bluetooth etc.
-TESTING = False
-
-import sys
-# for wrt
-sys.path.append('/root/python')
-import httplib
-import time
-import traceback
-import binascii
-import hmac
-import zlib
-import urllib
-import urllib2
-
-import config
-
-from utils import monotonic_time, retry, readline, crc16
-
-lightblue = None
-try:
-    import lightblue
-except ImportError:
-    import bluetooth
-
-def get_socket(addr):
-    if lightblue:
-        s = lightblue.socket()
-        s.connect((addr, 1))
-        s.settimeout(3)
-    else:
-        s = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
-        s.connect((addr, 1))
-
-    s.setblocking(False)
-
-    return s
-
-
-@retry()
-def fetch(sock):
-    print "fetch"
-    sock.send("fetch\n")
-
-    crc = 0
-
-    lines = []
-    l = readline(sock)
-    if l != 'START\n':
-        print>>sys.stderr, "Bad expected START line '%s'\n" % l.rstrip('\n')
-        return None
-    crc = crc16(l, crc)
-
-    while True:
-        l = readline(sock)
-
-        crc = crc16(l, crc)
-
-        if l == 'END\n':
-            break
-
-        lines.append(l.rstrip('\n'))
-
-    print lines
-
-    l = readline(sock)
-    recv_crc = None
-    try:
-        k, v = l.rstrip('\n').split('=')
-        print k,v
-        if k == 'CRC':
-            recv_crc = int(v)
-        if recv_crc < 0 or recv_crc > 0xffff:
-            recv_crc = None
-    except ValueError:
-        pass
-
-    if recv_crc is None:
-        print>>sys.stderr, "Bad expected CRC line '%s'\n" % l.rstrip('\n')
-        return None
-
-    if recv_crc != crc:
-        print>>sys.stderr, "Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc)
-        return None
-
-    return lines
-
-@retry()
-def turn_off(sock):
-    if TESTING:
-        return 99
-    print>>sys.stderr, "sending btoff"
-    sock.send("btoff\n");
-    # read newline
-    l = readline(sock)
-    if not l:
-        print>>sys.stderr, "Bad response to btoff\n"
-        return None
-
-    if not l.startswith('off:'):
-        print>>sys.stderr, "Bad response to btoff '%s'\n" % l
-        return None
-    off, next_wake = l.rstrip().split(':')
-    print>>sys.stderr, "Next wake %s" % next_wake
-
-    return int(next_wake)
-
-@retry()
-def clear_meas(sock):
-    sock.send("clear\n");
-    l = readline(sock)
-    if l and l.rstrip() == 'cleared':
-        return True
-
-    print>>sys.stderr, "Bad response to clear %s\n" % str(l)
-    return False
-
-def send_results(lines):
-    enc_lines = binascii.b2a_base64(zlib.compress('\n'.join(lines)))
-    mac = hmac.new(config.HMAC_KEY, enc_lines).hexdigest()
-
-    url_data = urllib.urlencode( {'lines': enc_lines, 'hmac': mac} )
-    con = urllib2.urlopen(config.UPDATE_URL, url_data)
-    result = con.read(100)
-    if result == 'OK':
-        return True
-    else:
-        print>>sys.stderr, "Bad result '%s'" % result
-        return False
-
-def do_comms(sock):
-    args = sys.argv[1:]
-    print "do_comms"
-    for a in args:
-        sock.send('%s\n' % a)
-
-    while True:
-        l = readline(sock)
-	if not l:
-		print '.',
-		sys.stdout.flush()
-	else:
-		print l
-
-testcount = 0
-
-def sleep_for(secs):
-    until = monotonic_time() + secs
-    while True:
-        length = until - monotonic_time()
-        if length <= 0:
-            return
-        time.sleep(length)
-
-def main():
-    next_wake_time = 0
-
-    while True:
-        sock = None
-        try:
-            sock = get_socket(BTADDR)
-        except Exception, e:
-            print>>sys.stderr, "Error connecting:"
-            traceback.print_exc(file=sys.stderr)
-        sleep_time = SLEEP_TIME
-        if sock:
-            next_wake = None
-            try:
-                next_wake_interval = do_comms(sock)
-                next_wake_time = time.time() + next_wake_interval
-            except Exception, e:
-                print>>sys.stderr, "Error in do_comms:"
-                traceback.print_exc(file=sys.stderr)
-            if next_wake_time > time.time():
-                sleep_time = min(next_wake_time - time.time() - EXTRA_WAKEUP, sleep_time)
-
-        print "Sleeping for %d" % sleep_time
-        sleep_for(sleep_time)
-
-if __name__ == '__main__':
-    main()
--- a/server/ts.py	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-#!/usr/bin/env python2.7
-
-# time that the bluetooth takes to get going?
-EXTRA_WAKEUP = -3
-
-FETCH_TRIES = 3
-
-# avoid turning off the bluetooth etc.
-TESTING = False
-
-import sys
-# for wrt
-sys.path.append('/root/python')
-import httplib
-import time
-import traceback
-import binascii
-import hmac
-import zlib
-import urllib
-import urllib2
-import logging
-import socket
-
-L = logging.info
-W = logging.warning
-E = logging.error
-
-import config
-
-from utils import monotonic_time, retry, readline, crc16
-import utils
-
-import bluetooth
-
-def get_socket(addr):
-    s = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
-    L("connecting")
-    s.connect((addr, 1))
-    s.setblocking(False)
-    s.settimeout(1)
-            
-    return s
-
-
-def flush(sock):
-    ret = []
-    while True:
-        l = readline(sock)
-        if l:
-            ret.append(l)
-        else:
-            break
-    return ret
-
-def encode_extra(extra_lines):
-    return ['extra%d=%s' % (n, l.strip()) for (n,l) in enumerate(extra_lines)]
-
-@retry()
-def fetch(sock):
-    extra_lines = flush(sock)
-    sock.send("fetch\n")
-
-    crc = 0
-
-    lines = []
-    l = readline(sock)
-    if not l:
-        return None
-
-    if l != 'START\n':
-        W("Bad expected START line '%s'\n" % l.rstrip('\n'))
-        extra_lines.append(l)
-        return encode_extra(extra_lines)
-    crc = crc16(l, crc)
-
-    while True:
-        l = readline(sock)
-
-        crc = crc16(l, crc)
-
-        if l == 'END\n':
-            break
-
-        lines.append(l.rstrip('\n'))
-
-    lines += encode_extra(extra_lines)
-
-    for d in lines:
-        L("Received: %s" % d)
-        
-    l = readline(sock)
-    recv_crc = None
-    try:
-        k, v = l.rstrip('\n').split('=')
-        if k == 'CRC':
-            recv_crc = int(v)
-        if recv_crc < 0 or recv_crc > 0xffff:
-            recv_crc = None
-    except ValueError:
-        pass
-
-    if recv_crc is None:
-        W("Bad expected CRC line '%s'\n" % l.rstrip('\n'))
-        return None
-
-    if recv_crc != crc:
-        W("Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc))
-        return None
-
-    return lines
-
-@retry()
-def turn_off(sock):
-    if TESTING:
-        return 99
-    L("Sending btoff")
-    flush(sock)
-    sock.send("btoff\n");
-    # read newline
-    l = readline(sock)
-    if not l:
-        W("Bad response to btoff")
-        return None
-
-    if not l.startswith('next_wake'):
-        W("Bad response to btoff '%s'" % l)
-        return None
-    L("Next wake line %s" % l)
-
-    toks = dict(v.split('=') for v in l.split(','))
-
-    rem = int(toks['rem'])
-    tick_secs = int(toks['tick_secs'])
-    tick_wake = int(toks['tick_wake']) + 1
-    next_wake = int(toks['next_wake'])
-
-    rem_secs = float(rem) / tick_wake * tick_secs
-
-    next_wake_secs = next_wake - rem_secs
-    L("next_wake_secs %f\n", next_wake_secs)
-    return next_wake_secs
-
-@retry()
-def clear_meas(sock):
-    flush(sock)
-    sock.send("clear\n");
-    l = readline(sock)
-    if l and l.rstrip() == 'cleared':
-        return True
-
-    E("Bad response to clear '%s'" % str(l))
-    return False
-
-def send_results(lines):
-    enc_lines = binascii.b2a_base64(zlib.compress('\n'.join(lines)))
-    mac = hmac.new(config.HMAC_KEY, enc_lines).hexdigest()
-
-    url_data = urllib.urlencode( {'lines': enc_lines, 'hmac': mac} )
-    con = urllib2.urlopen(config.UPDATE_URL, url_data)
-    result = con.read(100)
-    if result == 'OK':
-        return True
-    else:
-        W("Bad result '%s'" % result)
-        return False
-
-def do_comms(sock):
-    L("do_comms")
-    d = None
-    # serial could be unreliable, try a few times
-    d = fetch(sock)
-    if not d:
-        return
-
-    res = send_results(d)
-    if not res:
-        return
-
-    clear_meas(sock)
-
-    next_wake = 600
-    #next_wake = turn_off(sock)
-    #sock.close()
-    return next_wake
-
-testcount = 0
-
-def sleep_for(secs):
-    until = monotonic_time() + secs
-    while True:
-        length = until - monotonic_time()
-        if length <= 0:
-            return
-        time.sleep(length)
-
-def setup_logging():
-    logging.basicConfig(format='%(asctime)s %(message)s', 
-            datefmt='%m/%d/%Y %I:%M:%S %p',
-            level=logging.INFO)
-
-def get_net_socket(host, port):
-    s = socket.create_connection((host, port))
-    s.setblocking(False)
-    s.settimeout(1)
-    return s
-
-def main():
-    setup_logging()
-
-    L("Running templog rfcomm server")
-
-    if '--daemon' in sys.argv:
-        utils.cheap_daemon()
-
-    next_wake_time = 0
-
-    while True:
-        sock = None
-        try:
-            sock = get_net_socket(config.SERIAL_HOST, config.SERIAL_PORT)
-        except Exception, e:
-            #logging.exception("Error connecting")
-            pass
-
-        if not sock:
-            sleep_for(config.SLEEP_TIME)
-            continue
-
-        while True:
-            try:
-                do_comms(sock)
-                sleep_for(config.SLEEP_TIME)
-            except Exception, e:
-                logging.exception("Error in do_comms")
-                break
-
-if __name__ == '__main__':
-    main()
--- a/server/utils.py	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-import os
-import sys
-#import ctypes
-import time
-import select
-import logging
-
-L = logging.info
-W = logging.warning
-E = logging.error
-
-DEFAULT_TRIES = 3
-READLINE_SELECT_TIMEOUT = 1
-
-__all__ = ('monotonic_time', 'retry')
-
-clock_gettime = None
-no_clock_gettime = True
-def monotonic_time():
-    global clock_gettime
-    global no_clock_gettime
-    if no_clock_gettime:
-        return time.time()
-
-    class timespec(ctypes.Structure):
-        _fields_ = [
-            ('tv_sec', ctypes.c_long),
-            ('tv_nsec', ctypes.c_long)
-        ]
-    if not clock_gettime:
-        try:
-            librt = ctypes.CDLL('librt.so.0', use_errno=True)
-            clock_gettime = librt.clock_gettime
-            clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
-        except:
-            W("No clock_gettime(), using fake fallback.")
-            no_clock_gettime = True
-            return time.time()
-        
-    t = timespec()
-    CLOCK_MONOTONIC = 1 # see <linux/time.h>
-
-    if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
-        errno_ = ctypes.get_errno()
-        raise OSError(errno_, os.strerror(errno_))
-    return t.tv_sec + t.tv_nsec * 1e-9
-
-# decorator, tries a number of times, returns None on failure, sleeps between
-# Must be used as "@retry()" if arguments are defaulted
-def retry(retries=DEFAULT_TRIES, try_time = 1):
-    def inner(func):
-        def new_f(*args, **kwargs):
-            for i in range(retries):
-                d = func(*args, **kwargs)
-                if d is not None:
-                    return d
-                time.sleep(try_time)
-            return None
-
-        new_f.func_name = func.func_name
-        return new_f
-    return inner
-
-def readline(sock):
-    timeout = READLINE_SELECT_TIMEOUT
-    buf = ''
-    while True:
-        (rlist, wlist, xlist) = select.select([sock], [], [], timeout)
-        if sock not in rlist:
-            # hit timeout
-            return None
-
-        c = sock.recv(1)
-        if c == '':
-            # lightblue timeout
-            return None
-        if c == '\r':
-            continue
-
-        buf += c
-        if c == '\n':
-            return buf
-
-# from http://blog.stalkr.net/2011/04/pctf-2011-32-thats-no-bluetooth.html
-def crc16(buff, crc = 0, poly = 0x8408):
-    l = len(buff)
-    i = 0
-    while i < l:
-        ch = ord(buff[i])
-        uc = 0
-        while uc < 8:
-            if (crc & 1) ^ (ch & 1):
-                crc = (crc >> 1) ^ poly
-            else:
-                crc >>= 1
-            ch >>= 1
-            uc += 1
-        i += 1
-    return crc
-
-def cheap_daemon():
-    L("Daemonising.")
-    sys.stdout.flush()
-    sys.stderr.flush()
-    out = file('/dev/null', 'a+')
-    os.dup2(out.fileno(), sys.stdout.fileno())
-    os.dup2(out.fileno(), sys.stderr.fileno())
-
-    try:
-        pid = os.fork()
-        if pid > 0:
-            sys.exit(0)
-    except OSError, e:
-        E("Bad fork()")
-        sys.exit(1)
-
-    os.setsid()
-
-    try:
-        pid = os.fork()
-        if pid > 0:
-            sys.exit(0)
-    except OSError, e:
-        E("Bad fork()")
-        sys.exit(1)
-
-
--- a/simple_ds18b20.c	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-// Matt Johnston 2012
-// Based on ds18x20.c by Martin Thomas, in turn based on code by 
-// Peter // Dannegger and others.
-//
-#include <stdio.h>
-#include <avr/pgmspace.h>
-
-#include "ds18x20.h"
-#include "onewire.h"
-#include "crc8.h"
-
-#include "simple_ds18b20.h"
-
-uint8_t 
-simple_ds18b20_start_meas(uint8_t id[])
-{
-	uint8_t ret;
-
-	ow_reset();
-	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
-		ow_command_with_parasite_enable(DS18X20_CONVERT_T, id);
-		ret = DS18X20_OK;
-	} 
-	else { 
-		ret = DS18X20_START_FAIL;
-	}
-
-	return ret;
-}
-
-static uint8_t 
-read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
-{
-	uint8_t i;
-	uint8_t ret;
-
-	ow_command( DS18X20_READ, id );
-	for ( i = 0; i < n; i++ ) {
-		sp[i] = ow_byte_rd();
-	}
-	if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
-		ret = DS18X20_ERROR_CRC;
-	} else {
-		ret = DS18X20_OK;
-	}
-
-	return ret;
-}
-
-int16_t 
-ds18b20_raw16_to_decicelsius(uint16_t measure)
-{
-	uint8_t  negative;
-	int16_t  decicelsius;
-	uint16_t fract;
-
-	// check for negative 
-	if ( measure & 0x8000 )  {
-		negative = 1;       // mark negative
-		measure ^= 0xffff;  // convert to positive => (twos complement)++
-		measure++;
-	}
-	else {
-		negative = 0;
-	}
-
-	decicelsius = (measure >> 4);
-	decicelsius *= 10;
-
-	// decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
-	// 625/1000 = 640/1024
-	fract = ( measure & 0x000F ) * 640;
-	if ( !negative ) {
-		fract += 512;
-	}
-	fract /= 1024;
-	decicelsius += fract;
-
-	if ( negative ) {
-		decicelsius = -decicelsius;
-	}
-
-	if ( decicelsius == 850 || decicelsius < -550 || decicelsius > 1250 ) {
-		return DS18X20_INVALID_DECICELSIUS;
-	} else {
-		return decicelsius;
-	}
-}
-
-uint8_t 
-simple_ds18b20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
-{
-    uint16_t reading;
-	uint8_t ret;
-
-    ret = simple_ds18b20_read_raw(id, &reading);
-    if (ret == DS18X20_OK)
-    {
-        *decicelsius = ds18b20_raw16_to_decicelsius(reading);
-    }
-    return ret;
-}
-
-uint8_t 
-simple_ds18b20_read_raw( uint8_t id[], uint16_t *reading )
-{
-	uint8_t sp[DS18X20_SP_SIZE];
-	uint8_t ret;
-	
-	if (id)
-	{
-		ow_reset();
-	}
-	ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
-	if ( ret == DS18X20_OK ) {
-        *reading = sp[0] | (sp[1] << 8);
-	}
-	return ret;
-}
-
-static void 
-printhex_nibble(const unsigned char b, FILE *stream)
-{
-	unsigned char  c = b & 0x0f;
-	if ( c > 9 ) { 
-		c += 'A'-10; 
-	}
-	else {
-		c += '0';
-	}
-	fputc(c, stream);
-}
-
-void 
-printhex_byte(const unsigned char b, FILE *stream)
-{
-	printhex_nibble( b >> 4, stream);
-	printhex_nibble( b, stream);
-}
-
-void
-printhex(uint8_t *id, uint8_t n, FILE *stream)
-{
-	for (uint8_t i = 0; i < n; i++)
-	{
-		if (i > 0)
-		{
-			fputc(' ', stream);
-		}
-		printhex_byte(id[i], stream);
-	}
-}
-
-
-uint8_t 
-simple_ds18b20_read_all()
-{
-	uint8_t id[OW_ROMCODE_SIZE];
-	for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
-	{
-		diff = ow_rom_search( diff, &id[0] );
-
-		if( diff == OW_PRESENCE_ERR ) {
-			printf_P( PSTR("No Sensor found\r") );
-			return OW_PRESENCE_ERR; // <--- early exit!
-		}
-		
-		if( diff == OW_DATA_ERR ) {
-			printf_P( PSTR("Bus Error\r") );
-			return OW_DATA_ERR;     // <--- early exit!
-		}
-
-		int16_t decicelsius;
-		uint8_t ret = simple_ds18b20_read_decicelsius(NULL, &decicelsius);
-		if (ret != DS18X20_OK)
-		{
-			printf_P(PSTR("Failed reading\r"));
-			return OW_DATA_ERR;
-		}
-
-		printf_P(PSTR("DS18B20 %d: "), diff);
-		if (crc8(id, OW_ROMCODE_SIZE))
-		{
-			printf_P(PSTR("CRC fail"));
-		}
-		printhex(id, OW_ROMCODE_SIZE, stdout);
-		printf_P(PSTR(" %d.%d ºC\n"), decicelsius/10, decicelsius % 10);
-	}
-	printf_P(PSTR("Done sensors\n"));
-	return DS18X20_OK;
-}
-
--- a/simple_ds18b20.h	Sun Mar 30 20:32:19 2014 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-#ifndef SIMPLE_DS18B20_H_
-#define SIMPLE_DS18B20_H_
-#include <stdint.h>
-#include <stdio.h>
-
-#include "ds18x20.h"
-
-uint8_t simple_ds18b20_start_meas(uint8_t id[]);
-void printhex(uint8_t *id, uint8_t n, FILE *stream);
-void printhex_byte( const unsigned char  b, FILE *stream );
-uint8_t simple_ds18b20_read_decicelsius( uint8_t id[], int16_t *decicelsius );
-int16_t ds18b20_raw16_to_decicelsius(uint16_t measure);
-uint8_t simple_ds18b20_read_raw( uint8_t id[], uint16_t *reading );
-uint8_t simple_ds18b20_read_all();
-
-#endif // SIMPLE_DS18B20_H_