Clock/temperature display for my Father

First bit:

/*
  WeatherStation:
    Created by Gavin Maxwell, 2010

*/

#include <WProgram.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <Wire.h>
#include <DS1307.h>

// --> START PIN ASSIGNMENTS

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd( 17, 16, 12, 11, 10, 9 ); // modified for better board routing

#define TEMP_PIN 0            // analog IN pin 0
#define TEMP_REF_PIN 1        // analog IN pin 1
#define RESET_MINMAX_PIN  13  // button to reset the stored values in EEPROM

#define INT_0 0  // SQW interrupt from DS1307

// --> END PIN ASSIGNMENTS

int rtc[ DS1307_MAX_ITEMS ];
char* DOW[8] = { "", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };

#define MV_PER_DEGREE 10 // each 10mV is 1C
#define FULLSCALE_MV ((float)(4700)) // 5000 mV = 1024 from the ADC - actually 4700mV is approx what is supplied to LM35
#define FULLSCALE_ADC ((float)(1024)) // ADC returns from 0 - 1023 so 1024 unique values
#define MV_PER_ADC_STEP ((float)( FULLSCALE_MV / FULLSCALE_ADC )) // mV per ADC increment
#define INTER_READ_DELAY 20 // milliseconds between reads
#define UPDATE_INTERVAL  10000 // milliseconds between updates
#define USE_GROUND_REF 1

#define TEMP_SAMPLES 20 // number of samples to average

// EEPROM Addresses
#define MIN_TEMP_ADDRESS  0x00
#define MAX_TEMP_ADDRESS  0x01
#define CLOCK_SET_ADDRESS 0x02
#define CALIBRATION_ADDRESS 0x03  // NOT USED

unsigned long lastUpdate;
long minTemp = 255;
long maxTemp = -255;
long LM35Calibration = -1;  // Rough as nails

boolean showColon = true; // flag to blink the colon seperator

#define DEGREE_CHAR 4
#define STEP1_CHAR 5
#define STEP2_CHAR 6
#define STEP3_CHAR 7
#define ARROW_CHAR 0x7E

byte degree[8] = {
  B01100,
  B10010,
  B10010,
  B01100,
  B00000,
  B00000,
  B00000,
};
byte step1[8] = {
  B00000,
  B01110,
  B10001,
  B10001,
  B10001,
  B01110,
  B00000,
};
byte step2[8] = {
  B00000,
  B01110,
  B11111,
  B11011,
  B11111,
  B01110,
  B00000,
};
byte step3[8] = {
  B00000,
  B01110,
  B11111,
  B11111,
  B11111,
  B01110,
  B00000,
};

volatile boolean updateTime = true;

// DS1307 1Hz pulse ISR - set our flag and get out!
void pulseISR()
{
  updateTime = true;
}

//
// Setup all of our pins, initialise the RTC, serial port and LCD
//
void setup()
{
  int i, ndx;
  pinMode( TEMP_PIN, INPUT );
  pinMode( TEMP_REF_PIN, INPUT );
  
  pinMode( RESET_MINMAX_PIN, INPUT );
  digitalWrite( RESET_MINMAX_PIN, HIGH );  // internal pull-up - switch will pull low to indicate reset
  
  // DS1307 sends a 1Hz pulse - we use this to update the display  
  attachInterrupt( INT_0, pulseISR, FALLING );
  
  Serial.begin( 9600 );

  // read the stored min and max
  // values will be 255 if never written before
  // if max has never been recorded set it super low
  // to force an update first time we measure
  minTemp = EEPROM.read( MIN_TEMP_ADDRESS );
  maxTemp = EEPROM.read( MAX_TEMP_ADDRESS );
  if ( maxTemp == 255 )
    maxTemp = -255;
    
  // EEPROM stores a unsigned byte, so we need to handle
  // negatives. 200 limit OK as sensor goes down to -55 (0xC9, 201)
  if ( minTemp > 200 )
    minTemp = minTemp - 256;
  
  if ( maxTemp > 200 )
    maxTemp = maxTemp - 256;

  // if EEPROM has never been set then use a default date
  if ( EEPROM.read( CLOCK_SET_ADDRESS ) == 255 )
  {
    RTC.stop();
    RTC.set( DS1307_SEC, 1 );
    RTC.set( DS1307_MIN, 17 );
    RTC.set( DS1307_HR, 15 );
    RTC.set( DS1307_DOW, 6 );
    RTC.set( DS1307_DATE, 16 );
    RTC.set( DS1307_MTH, 10 );
    RTC.set( DS1307_YR, 10 );
    RTC.start();
    EEPROM.write( CLOCK_SET_ADDRESS, 1 );
  }
  
  // Define custom characters
  lcd.createChar( DEGREE_CHAR, degree );
  lcd.createChar( STEP1_CHAR, step1 );
  lcd.createChar( STEP2_CHAR, step2 );
  lcd.createChar( STEP3_CHAR, step3 );

  // set up the LCD's number of rows and columns: 
  lcd.begin( 16, 2 );
  
  // Get the current time and display Xmas Card if it's Xmas!
  RTC.get( rtc, true );

  // SNIP FOR PRIVACY REASONS
  
  // enable 1Hz square wave output
  RTC.enableOutput();
  RTC.setOutputRate( 0 );
  
  lcd.clear();
  
  lastUpdate = millis() - UPDATE_INTERVAL;
}

//
// Simple formatter of numeric values
//
void BufferPrint( char *buffer, unsigned long value, unsigned long i, int bufLen )
{
  unsigned long temp;
  int bufindex = 0;
 
  if ( buffer )
  {
    memset( buffer, 0, bufLen );
    while ( i > 0 )
    {
      temp = value / i;
      value -= temp * i;
      buffer[ bufindex++ ] = (char)( '0' + temp );
      i/=10;
    }
  }
}

//
// Retrieves updated time from DS1307, formats it then displays on LCD
//
void UpdateTime()
{
  const int timeBufLen = 8;
  char buf[ timeBufLen ];

  RTC.get( rtc, true );

  lcd.setCursor( 0, 0 );
  BufferPrint( buf, rtc[ DS1307_HR ], 10, timeBufLen );
  lcd.print( buf );
  lcd.print( showColon ? ":" : " " );
  showColon = !showColon;
  BufferPrint( buf, rtc[ DS1307_MIN ], 10, timeBufLen );
  lcd.print( buf );

  lcd.print( " " );

  // Check DOW is a valid value
  if ( rtc[ DS1307_DOW ] <= 0 || rtc[ DS1307_DOW ] > 7 )
    lcd.print( "???" );
  else
    lcd.print( DOW[ rtc[ DS1307_DOW ] ] );
  lcd.print( " " );

  BufferPrint( buf, rtc[ DS1307_DATE ], 10, timeBufLen );
  lcd.print( buf );
  lcd.print( "/" );
  BufferPrint( buf, rtc[ DS1307_MTH ], 10, timeBufLen );
  lcd.print( buf );
  
  // reset flag until next interrupt
  updateTime = false;
}

//
// Decode the entered time and set the DS1307
// Format: THHMMSSWDDMMYY
// where W is 1->7 for Monday->Sunday
//
void HandleTimeSet()
{
  int inByte = Serial.read();
  
  if ( inByte == 't' || inByte == 'T' )
  {
    int b1, b2, hh, mm, ss, wd, dd, mo, yy;
    
    Serial.println( "SETTING THE TIME" );
    b1 = Serial.read();
    b2 = Serial.read();
    hh = ( ( b1 - '0')  * 10 ) + ( b2 - '0' );
    b1 = Serial.read();
    b2 = Serial.read();
    mm = ( ( b1 - '0')  * 10 ) + ( b2 - '0' );
    b1 = Serial.read();
    b2 = Serial.read();
    ss = ( ( b1 - '0')  * 10 ) + ( b2 - '0' );
    b1 = Serial.read();
    wd = ( b1 - '0');
    b1 = Serial.read();
    b2 = Serial.read();
    dd = ( ( b1 - '0')  * 10 ) + ( b2 - '0' );
    b1 = Serial.read();
    b2 = Serial.read();
    mo = ( ( b1 - '0')  * 10 ) + ( b2 - '0' );
    b1 = Serial.read();
    b2 = Serial.read();
    yy = ( ( b1 - '0')  * 10 ) + ( b2 - '0' );

    RTC.stop();
    RTC.set( DS1307_SEC, ss );
    RTC.set( DS1307_MIN, mm );
    RTC.set( DS1307_HR, hh );
    RTC.set( DS1307_DOW, wd );
    RTC.set( DS1307_DATE, dd );
    RTC.set( DS1307_MTH, mo );
    RTC.set( DS1307_YR, yy );
    RTC.start();
  }
  else if ( inByte == 'c' || inByte == 'C' )
  {
    Serial.println( "TEMPERATURE CALIBRATION NOT IMPLEMENTED YET" );
    
  }
}

//
// A press on the rest button over a set duration indicates
// we need to clear the current stored min and max temperatures
//
void CheckForResetMinMax()
{
  // Handle resetting the min and max temp values
  if ( digitalRead( RESET_MINMAX_PIN ) == LOW )
  {
    long press = millis();
    
    // spin whilst the buton is down
    while ( digitalRead( RESET_MINMAX_PIN ) == LOW )
    {
      lcd.setCursor( 0, 1 );
      if ( millis() > press + 1500 )
        lcd.print( "T:<RELEASE>     " );
      else
        lcd.print( "T:<HOLD 2 RESET>" );
    }
    
    // was it down long enough to indicate a real press
    if ( millis() > press + 1500 )
    {
      lcd.setCursor( 0, 1 );
      lcd.print( "T:<RESETTING>   " );

      minTemp = 255;
      maxTemp = -255;
      EEPROM.write( MIN_TEMP_ADDRESS, 255 );
      EEPROM.write( MAX_TEMP_ADDRESS, 255 );
    }

    // force a temp update
    lastUpdate = millis() - UPDATE_INTERVAL;
  }
}