Code: Select all
/* Auxillary LCD monitor connected to the ReefAngel Controller (328)
requires a custom cable to connect from I2C main to the serial port
The following features are enabled for this File: 
#define DisplayLEDPWM
#define RelayExp
#define InstalledRelayExpansionModules 1
#define CUSTOM_MAIN
#define COLORS_PDE
#define FONT_8x8
#define NUMBERS_8x8
#define NUMBERS_16x16
*/
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <ReefAngel.h>
#include <IO.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <avr/wdt.h>
//screen set-up
#define NumScreens 9
int ScreenID=0;
//define for data over I2C
int maxTemp=0;
int minTemp=2000;
int maintemp=800;
int roomtemp=780;
int sumptemp=780;
int ph=700;
int maxPH=600;
int minPH=900;
int moonlight=0;
byte TempRelay =15;
byte TempRelay2=15;
int wavetime=0;
int wavetime2=0;
int flow0=0;
int flow1=0;
int flow2=0;
int wmaker2;
byte mhour;
byte mminute;
byte msecond;
byte mday;
byte mmonth;
int myear;
byte Overflow;
byte Reservoir;
byte LATO;
byte HATO;
byte level;
byte atos;
//Analog Clock constants
    const float pi = 3.141592653;
    byte clock_center_x = 65;
    byte clock_center_y = 65;
    byte clock_radius = 55;
    byte secondhand_radius = 33;
    float secondangle;
    byte secondend_x;
    byte secondend_y;
    float minuteangle;
    float hourangle;
   // Analog Clock Structure
       int minutebase_radius = 3;
       int minutehand_radius = 33;
       int hourbase_radius = 3;
       int hourhand_radius = 25;   
       int seconds_hand_x, seconds_hand_y, minutes_hand_x, minutes_hand_y, hours_hand_x, hours_hand_y;
       int hours_hand_base_x, hours_hand_base_y, hours_hand_base_x1, hours_hand_base_y1;
       int minutes_hand_base_x, minutes_hand_base_y, minutes_hand_base_x1, minutes_hand_base_y1; 
       int minutebase_x, minutebase_y, minutebase_x1, minutebase_y1; 
       int minuteend_x, minuteend_y; 
       int hourbase_x, hourbase_y, hourbase_x1, hourbase_y1; 
       int hourend_x, hourend_y; 
       float minfloat;
//time stamp
time_t tsmax=now();
time_t tsmin=now();
time_t PHmax=now();
time_t PHmin=now();
int mastertime;
// Moon Global Variables - Thanks Deckoz2302!
byte ThisPhase;
double AG;
double IP;
byte MoonPWMValue;
long YY, MM, K1, K2, K3, JD;
// Draw Minutes Hand
void draw_minute(int color)
{
  Drawline(minutebase_x, minutebase_y, minutebase_x1, minutebase_y1, color); 
  Drawline(minutebase_x, minutebase_y, minuteend_x, minuteend_y, color); 
  Drawline(minutebase_x1, minutebase_y1, minuteend_x, minuteend_y, color); 
}
// Draw Hour Hand
void draw_hour(int color)
{
   Drawline(hourbase_x, hourbase_y, hourbase_x1, hourbase_y1, color); 
   Drawline(hourbase_x, hourbase_y, hourend_x, hourend_y, color); 
   Drawline(hourbase_x1, hourbase_y1, hourend_x, hourend_y, color); 
}
void Drawline (int x0, int y0, int x1, int y1, int color) 
{
  int dy = y1 - y0;
  int dx = x1 - x0;
  int stepx, stepy;
  if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
  if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
  dy <<= 1; // dy is now 2*dy
  dx <<= 1; // dx is now 2*dx
  ReefAngel.LCD.PutPixel(color, x0, y0);
  if (dx > dy) {
    int fraction = dy - (dx >> 1); // same as 2*dy - dx
    while (x0 != x1) {
      if (fraction >= 0) {
        y0 += stepy;
        fraction -= dx; // same as fraction -= 2*dx
        }
      x0 += stepx;
      fraction += dy; // same as fraction -= 2*dy
      ReefAngel.LCD.PutPixel(color, x0, y0);
    }
  } else {
  int fraction = dx - (dy >> 1);
  while (y0 != y1) {
  if (fraction >= 0) {
    x0 += stepx;
    fraction -= dy;
    }
  y0 += stepy;
  fraction += dx;
  ReefAngel.LCD.PutPixel(color, x0, y0);
  }
  }}
void DrawTime(byte x, byte y, byte FGcolor, byte BGcolor, time_t ts)
{
    char text[13];
    char temp[]="  ";
    strcpy(text,"");
    itoa(hourFormat12(ts),temp,10);
    if (temp[1]==0) strcat(text,"0");
    strcat(text,temp);
    strcat(text,":");
    itoa(minute(ts),temp,10);
    if (temp[1]==0) strcat(text,"0");
    strcat(text,temp);
    strcat(text,":");
    itoa(second(ts),temp,10);
    if (temp[1]==0) strcat(text,"0");
    strcat(text,temp);
    if (isAM(ts))
    {
        strcat(text," AM");
    }
    else
    {
        strcat(text," PM");
    }
    ReefAngel.LCD.DrawText(FGcolor, BGcolor, x, y, text);
}
void DrawCircle(int a, int b, int r, byte color)
{
  int f = 1 - r;  
  int ddF_x = 1;  
  int ddF_y = -2 * r;  
  int x = 0;  
  int y = r;
  
 ReefAngel.LCD.PutPixel(color, a, b+r);  
 ReefAngel.LCD.PutPixel(color ,a, b-r);  
 ReefAngel.LCD.PutPixel(color, a+r, b);  
 ReefAngel.LCD.PutPixel(color, a-r, b);
 while (x<y) 
 {    
 if (f >= 0) 
 {      y--;
       ddF_y += 2;      
       f += ddF_y;    
   }    
   x++;    
   ddF_x += 2;    
   f += ddF_x;
   
   ReefAngel.LCD.PutPixel(color, a + x, b + y);
   ReefAngel.LCD.PutPixel(color, a - x, b + y);
   ReefAngel.LCD.PutPixel(color, a + x, b - y);
   ReefAngel.LCD.PutPixel(color, a - x, b - y);
   ReefAngel.LCD.PutPixel(color, a + y, b + x);
   ReefAngel.LCD.PutPixel(color, a - y, b + x);
   ReefAngel.LCD.PutPixel(color, a + y, b - x);
   ReefAngel.LCD.PutPixel(color, a - y, b - x);
   }
}
void FillCircle(int a, int b, int r, byte color) 
{  
   int f = 1 - r;  
   int ddF_x = 1;  
   int ddF_y = -2 * r;  
   int x = 0;  
   int y = r;  
for (int i=b-r; i<=b+r; i++) 
{    
  ReefAngel.LCD.PutPixel(color, a, i);  
}  
while (x<y) 
{    
if (f >= 0) 
{      
   y--;      
   ddF_y += 2;      
   f += ddF_y;    
}    
   x++;    
   ddF_x += 2;    
   f += ddF_x;      
   for (int i=b-y; i<=b+y; i++) 
{      
ReefAngel.LCD.PutPixel(color, a+x, i);      
ReefAngel.LCD.PutPixel(color, a-x, i);    
}     
for (int i=b-x; i<=b+x; i++) 
{      
ReefAngel.LCD.PutPixel(color,a+y, i);     
ReefAngel.LCD.PutPixel(color,a-y, i);    
}      
}
}
void DrawCircleBox (byte x, byte y, byte RelayData)
{
 byte b = 0;
 byte c = 0;
 byte d = 0;
    for (byte a=0;a<2;a++)
      {
        DrawCircle ((a*10)+x,y+30,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle((a*10)+x,y+30,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle((a*10)+x,y+30,3,OutletOffBGColor);
        }
      }
   for (byte a=2;a<4;a++)
      {
        b=(a-2)*10;
       DrawCircle (b+x,y+20,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle(b+x,y+20,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle(b+x,y+20,3,OutletOffBGColor);
        }
      }
    for (byte a=4;a<6;a++)
      {
        c=(a-4)*10;
       DrawCircle (c+x,y+10,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle(c+x,y+10,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle(c+x,y+10,3,OutletOffBGColor);
        }
      }
    for (byte a=6;a<8;a++)
      {
        d=(a-6)*10;
       DrawCircle (d+x,y,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle(d+x,y,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle(d+x,y,3,OutletOffBGColor);
    
      }
      }
}
void DrawWeeklyAvg (byte hr, int sensor, byte color, byte x, byte y, byte z)
{
  const int numReadings = 7;
  int dailyread;
  int readings[numReadings];      // the readings from the analog input
  int index = 0;                  // the index of the current reading
  int total = 0;                  // the running total
  int average = 0;                // the average
  if (hour()==hr && minute()==0 && second()==0) 
  {
    dailyread=sensor;  
  total= total - readings[index];   // subtract the last reading:         
  readings[index] = dailyread;   // read from the sensor: 
  total= total + readings[index];   // add the reading to the total:       
     index = index + 1;  // advance to the next position in the array:                   
  if (index >= numReadings)     // if we're at the end of the array...           
    index = 0;       // ...wrap around to the beginning:                         
  average = total / numReadings;    // calculate the average:
  delay (1000);
  ReefAngel.LCD.DrawSingleMonitor(average, color, x, y, z);
  }
}
void DrawDailyAvg (int sensor, byte color, byte x, byte y, byte z)
{
  const int numReadings = 24;
  int dailyread;
  int readings[numReadings];      // the readings from the analog input
  int index = 0;                  // the index of the current reading
  int total = 0;                  // the running total
  int average = 0;                // the average
  if (minute()==0 && second()==0) 
  {
    dailyread=sensor;  
  total= total - readings[index];   // subtract the last reading:         
  readings[index] = dailyread;   // read from the sensor: 
  total= total + readings[index];   // add the reading to the total:       
     index = index + 1;  // advance to the next position in the array:                   
  if (index >= numReadings)     // if we're at the end of the array...           
    index = 0;       // ...wrap around to the beginning:                         
  average = total / numReadings;    // calculate the average:
  delay (1000);
  ReefAngel.LCD.DrawSingleMonitor(average, color, x, y, z);
  }
}
void setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  setTime(19,59,0,6,3,12);
  Wire.begin(10); // I2C address 10
  Wire.onReceive(receiveEvent);
  ReefAngel.Timer[LCD_TIMER].SetInterval(180);
  ReefAngel.Timer[LCD_TIMER].Start();  // start timer 
}
void loop()
{
  setTime(mhour,mminute,msecond,mday,mmonth,myear);
  if ( ReefAngel.Timer[LCD_TIMER].IsTriggered() )  // process screensaver timeout
	{// Screensaver timeout expired
	ReefAngel.LCD.BacklightOff();
	}
  if ( ReefAngel.Joystick.IsButtonPressed())
	{// turn the backlight on
	ReefAngel.LCD.BacklightOn();
        }
  // TODO check Timer[LCD_TIMER] code
  if ( ReefAngel.Timer[LCD_TIMER].Trigger == 0 )
	{
	ReefAngel.Timer[LCD_TIMER].Start();
	return;
	}// update the min and max temps
  if (now()%86400==0)
  {
    minTemp=maintemp;
    maxTemp=maintemp;
  }
  if (maintemp<minTemp) 
  {
    minTemp=maintemp;
    tsmin=now();
  }
  if (maintemp>maxTemp) 
  {
    maxTemp=maintemp;
    tsmax=now();
  }
  // update the min and max pH
if (now()%86400==0)
{
  minPH=ph;
  maxPH=ph;
}
if (ph<minPH) 
{
  minPH=ph;
  PHmin=now();
  
  
}
if (ph>maxPH) 
{
  maxPH=ph;
  PHmax=now();
}
  if (ReefAngel.Joystick.IsLeft() || ReefAngel.Joystick.IsDown()) 
  {
    ReefAngel.ClearScreen(DefaultBGColor);
    ScreenID--;
  }
  if (ReefAngel.Joystick.IsRight() || ReefAngel.Joystick.IsUp()) 
    {
    ReefAngel.ClearScreen(DefaultBGColor);
    ScreenID++;
    }
  if (ScreenID<0) ScreenID=NumScreens;
  if (ScreenID>=NumScreens) ScreenID=0;
  switch (ScreenID)
  {
  case 0:  //Initial first screen
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#1", Font8x8);
    // Display Temp Text
    ReefAngel.LCD.DrawLargeText(0,255,30,15,"Tank Temp", Font8x8);
    // Display the T1 temp  
    char text[7];
    ConvertNumToString(text, maintemp, 10);
    ReefAngel.LCD.Clear(255, 35, 25, 50, 60);
    if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
    else if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
    // Display pH Text
    ReefAngel.LCD.DrawLargeText(0,255,82,85,"  pH  ", Font8x8);
    // Display pH Value
    ConvertNumToString(text, ph, 100);
    ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (ph>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (ph>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
    // Display Sump Temp
    ReefAngel.LCD.DrawLargeText(0,255,8,50,"Sump Temp", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
    ConvertNumToString(text, sumptemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);
    // Display Room Temp
    ReefAngel.LCD.DrawLargeText(0,255,8,60,"Room Temp", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
    ConvertNumToString(text, roomtemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8); 
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (10,90,TempRelay);
    DrawCircleBox (40,90,TempRelay2);
    break;
  case 1:  //same as first screen with position changes
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#2", Font8x8);
    // Display Temp Text
    ReefAngel.LCD.DrawLargeText(0,255,30,15,"   pH    ", Font8x8);
    // Display the T1 temp 
    ConvertNumToString(text, ph, 100);
    ReefAngel.LCD.Clear(255, 35, 25, 50, 50);
    if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
    else if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
    // Display pH Text
    ReefAngel.LCD.DrawLargeText(0,255,25,105,"Tank", Font8x8);  
    // Display pH Value
    ConvertNumToString(text, maintemp, 10);
    ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (maintemp>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (maintemp>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
    // Display Flow0
    ReefAngel.LCD.DrawLargeText(0,255,8,50,"Pump1Flow", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
    ConvertNumToString(text, flow0, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);
    // Display Flow1
    ReefAngel.LCD.DrawLargeText(0,255,8,60,"Pump2Flow", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
    ConvertNumToString(text, flow1, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8);
    // Display light level 
    ReefAngel.LCD.DrawLargeText(0,255,8,70,"Moonlight", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 70, 132, 90);
    ConvertNumToString(text, moonlight, 1);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 70, text, Num8x8); 
// moonphase------------------------------------------------------------   
  YY = (year()) - floor((12 - (month())) / 10); 
  MM = (month()) + 9;
  if (MM >= 12)
  {
    MM = MM - 12;
  }
  K1 = floor(365.25 * (YY + 4712));
  K2 = floor(30.6 * MM + 0.5);
  K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;
  JD = K1 + K2 + (day()) + 59;
  if (JD > 2299160)
  {
    JD = JD - K3;
  }
  IP = (JD - 2451550.1) / 29.530588853;
  IP = IP - floor(IP);
  if (IP < 0)
  {
    IP = IP + 1;
  }
  AG = IP*29.53;
  
  if (AG < 1.84) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"New", Font8x8);
  else if (AG < 5.53) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waxing Crescent", Font8x8);
  else if (AG < 9.92) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"First Quarter", Font8x8);
  else if (AG < 12.91) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waxing Gibbous", Font8x8);   
  else if (AG < 16.61) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Full", Font8x8);    
  else if (AG < 20.30) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waning gibbous", Font8x8);    
  else if (AG < 23.99) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Last Quarter", Font8x8);    
  else if (AG < 27.68) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waning Crescent", Font8x8);    
  else  ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"New") ;  
    break;
  case 2:  //Temperature detail screen with sump and room temp, 24 hr. max/min, time stamps, and graph
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#3", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,10,15,"Temp Details", Font8x8);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,33,"TANK:");
    ReefAngel.LCD.DrawSingleMonitor(maintemp, COLOR_BLACK, 36, 33, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,43,"HI:");
    ReefAngel.LCD.DrawSingleMonitor(maxTemp, 0, 23, 43, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,43,"at");
    DrawTime(60,43,0, COLOR_WHITE,tsmax);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,53,"LO:");
    ReefAngel.LCD.DrawSingleMonitor(minTemp, 0, 23, 53, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,53,"at");
    DrawTime(60,53,0,COLOR_WHITE, tsmin);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,63,"Range:");
    ReefAngel.LCD.DrawSingleMonitor((maxTemp-minTemp), COLOR_BLACK, 46, 63, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,69,63,"degreesF");
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,73,"Avg:");
    DrawDailyAvg(maintemp, COLOR_BLACK, 43, 73, 1);  
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,83,"WeeklyAvg:");
    DrawWeeklyAvg(12,maintemp, COLOR_BLACK, 66, 83, 1);  
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor, 86,83,"at noon");
    ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor, 5 ,93,"R00M:");
    ReefAngel.LCD.DrawSingleMonitor(roomtemp, COLOR_BLACK, 36, 93, 10);
    ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor, 5, 103,"SUMP:");
    ReefAngel.LCD.DrawSingleMonitor(sumptemp, COLOR_BLACK, 36, 103, 10);
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#3", Font8x8);
    break;
  case 3:  //pH details
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,20,15,"pH Details", Font8x8);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,33,"pH:");
    ReefAngel.LCD.DrawSingleMonitor(ph, COLOR_BLACK, 36, 33, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,43,"HI:");
    ReefAngel.LCD.DrawSingleMonitor(maxPH, 0, 23, 43, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,48,43,"at");
    DrawTime(60,43,0, COLOR_WHITE,PHmax);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,53,"LO:");
    ReefAngel.LCD.DrawSingleMonitor(minPH, 0, 23, 53, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,48,53,"at");
    DrawTime(60,53,0,COLOR_WHITE, PHmin);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,63,"Range:");
    ReefAngel.LCD.DrawSingleMonitor((maxPH-minPH), COLOR_BLACK, 46, 63, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,73,"Avg:");
    DrawDailyAvg(ph, COLOR_BLACK, 43, 73, 100);  
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,83,"WeeklyAvg:");
    DrawWeeklyAvg(12,ph, COLOR_BLACK, 66, 83, 100);  
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 86,83,"at noon");
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,93,"WeeklyAvg:");
    DrawWeeklyAvg(0,ph, COLOR_BLACK, 66, 93, 100);  
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 86,93,"at midnt");
    break;
 case 4:  //relay box key
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#5", Font8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (56,46,TempRelay);
    ReefAngel.LCD.DrawLargeText(0,255,27,20,"RelayBox 1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44,"MainP", Font8x8); //7
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"WaveL", Font8x8); //5
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"MH LT", Font8x8); //3
    ReefAngel.LCD.DrawLargeText(0,255,7,74,"Heat2", Font8x8); //1
    ReefAngel.LCD.DrawLargeText(0,255,75,44,"Fans", Font8x8);  //8
    ReefAngel.LCD.DrawLargeText(0,255,75,54,"WaveR", Font8x8);  //6
    ReefAngel.LCD.DrawLargeText(0,255,75,64,"StdLT", Font8x8); //4
    ReefAngel.LCD.DrawLargeText(0,255,75,74,"Heat1", Font8x8);  //2
    break;
  case 5:  //relay box key
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#6", Font8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (56,46,TempRelay2);
    ReefAngel.LCD.DrawLargeText(0,255,27,20,"RelayBox 2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44,"Dose1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"Wave3", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"  ATO", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,74,"Chill", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,44,"Dose2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,54,"Wave4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,64,"PO4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,74,"Chill", Font8x8);
    break;
  case 6:  //level sensors
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#7", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,20,20,"Level Sensors", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44," Overflow", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"Reservoir", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"  Low ATO", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,74," High ATO", Font8x8);
    if (level == 0)
    {
      Overflow = 0;
      Reservoir = 0;
    }
    else if (level == 1)
    {
      Overflow = 1;
      Reservoir = 0;
    }
    else if (level == 2)
    {
      Overflow = 0;
      Reservoir = 1;
    }
    else if (level == 3)
    {
      Overflow = 1;
      Reservoir = 1;
    }
    if (atos == 0)
    {
      HATO = 1;
      LATO = 1;
    }
    else if (atos == 1)
    {
      HATO = 1;
      LATO = 0;
    }
    else if (atos == 2)
    {
      HATO = 0;
      LATO = 1;
    }
    else if (atos == 3)
    {
      HATO = 0;
      LATO = 0;
    }
    DrawCircle (90,48,5,COLOR_BLACK);
        if (Overflow == 1) 
        {
          FillCircle(90,48,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 44, 132, 54);
        }
        else if (Overflow == 0)
        {
          FillCircle(90,48,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,44,"HIGH", Font8x8);
        }
    DrawCircle (90,58,5,COLOR_BLACK);
        if (Reservoir == 1) 
        {
          FillCircle(90,58,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,54,"FILL", Font8x8);
        }
        else if (Reservoir == 0)
        {
          FillCircle(90,58,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 54, 132, 64);
        }
    DrawCircle (90,68,5,COLOR_BLACK);
        if (LATO == 1) 
        {
          FillCircle(90,68,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,64,"FILL", Font8x8);
        }
        else if (LATO == 0)
        {
          FillCircle(90,68,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 64, 132, 74);
        }
    DrawCircle (90,78,5,COLOR_BLACK);
        if (HATO == 1) 
        {
          FillCircle(90,78,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 74, 132, 84);
        }
        else if (HATO == 0)
        {
          FillCircle(90,78,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,74,"LOW", Font8x8);
        }        
       break;
  case 7:  //setclock
  // Analog clock is modified from the original source by Jeff Miller
  // Author: Jeff Miller   http://arduinofun.blogspot.com/
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    // Frame
    DrawCircle(clock_center_x, clock_center_y, clock_radius, COLOR_CORNFLOWERBLUE);
    DrawCircle(clock_center_x, clock_center_y, clock_radius - 1, COLOR_CORNFLOWERBLUE);        
    DrawCircle(clock_center_x, clock_center_y, clock_radius - 2, COLOR_CORNFLOWERBLUE);       
    // Face Tick Marks  (x = r cos theta, y = r sin theta)
    for (byte r=0; r < 12; r++) {
      float angle = (2 * pi / 12)*r;
      int tick_x_out = (clock_radius - 8) * cos (angle) + clock_center_x;
      int tick_y_out = (clock_radius - 8) * sin (angle) + clock_center_y;
      int tick_x_in = clock_radius *.72 * cos (angle) + clock_center_x;
      int tick_y_in = clock_radius * .72 * sin (angle) + clock_center_y;                
      Drawline(tick_x_in, tick_y_in, tick_x_out, tick_y_out, COLOR_CORNFLOWERBLUE);
      }
    // Face Characters
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x - 8,106," 6", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x - 8, 25,"12", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x + 34,clock_center_y," 3", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x - 50, clock_center_y - 4,"9 ", Font8x8);
   // Draw Seconds Hand
       secondangle = (2 * pi / 60) * second();
              if (second() > 15)
        {secondangle = secondangle -1.57;
        }
      else
        {secondangle = secondangle +4.71;
        }
       Drawline(clock_center_x, clock_center_y, secondend_x, secondend_y, WHITE);
       secondend_x = secondhand_radius * cos (secondangle) + clock_center_x;
       secondend_y = secondhand_radius * sin (secondangle) + clock_center_y;
       Drawline(clock_center_x, clock_center_y, secondend_x, secondend_y, BLACK);
// Redraw minutes hand since the section closest to the center gets erased by the seconds hand
       draw_minute(BLACK);
// Redraw hour hand
       draw_hour(BLACK);
// Draw Minutes Hand
       minuteangle = (2 * pi / 60) * minute();
       if (minute() > 15)
        {minuteangle = minuteangle -1.57;
        }
      else
        {minuteangle = minuteangle +4.71;
        }
        // Erase old minutes Hand
       draw_minute(WHITE);
  // Calculate Minute Hand Base
      minutebase_x = minutebase_radius * cos (minuteangle - pi/2) + clock_center_x;
      minutebase_y = minutebase_radius * sin (minuteangle - pi/2) + clock_center_y;
      minutebase_x1 = minutebase_radius * cos (minuteangle + pi/2) + clock_center_x;
      minutebase_y1 = minutebase_radius * sin (minuteangle + pi/2) + clock_center_y;
// Calculate Minute Hand Point
      minuteend_x = minutehand_radius * cos (minuteangle) + clock_center_x;
      minuteend_y = minutehand_radius * sin (minuteangle) + clock_center_y;
// Draw new minutes Hand
      draw_minute(BLACK);                         
// Redraw hour hand
      draw_hour(BLACK);
// Draw Hour Hand   
      minfloat = minute(); // Convert minute short to float
      hourangle = (2 * pi / 12) * ((hourFormat12()) + (minfloat/60)); // Find angle for hour hand
      hourangle = hourangle -1.57;
// Erase old Hour Hand
      draw_hour(WHITE);
// Calculate hour Hand Base
      hourbase_x = hourbase_radius * cos (hourangle - pi/2) + clock_center_x;
      hourbase_y = hourbase_radius * sin (hourangle - pi/2) + clock_center_y;
      hourbase_x1 = hourbase_radius * cos (hourangle + pi/2) + clock_center_x;
      hourbase_y1 = hourbase_radius * sin (hourangle + pi/2) + clock_center_y;
// Calculate hour Hand Point
      hourend_x = hourhand_radius * cos (hourangle) + clock_center_x;
      hourend_y = hourhand_radius * sin (hourangle) + clock_center_y;
// Draw new hours Hand
      draw_hour(BLACK);
    ReefAngel.LCD.DrawLargeText(0,255,110,110,"#8", Font8x8);
    ReefAngel.LCD.DrawDate(5,121);
    break;
  case 8:  //menu
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#9", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,20,15,"Power Heads", Font8x8);
    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 8, 33,"Top wave:");
    ReefAngel.LCD.Clear(255,78,33,103,43);
    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 8, 108,"Side wave:");
    ReefAngel.LCD.Clear(255,78,108,103,120);
    ReefAngel.LCD.DrawText(0,DefaultBGColor, 78, 108, wavetime);
//    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 104, 113,TempRelay2);
    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 104, 108,"sec");
  if ((TempRelay&(1<<5))==1<<5)
    {
    ReefAngel.LCD.Clear(255,5,75,90,105);
    ReefAngel.LCD.DrawLargeText(0,255,90,75,"<---", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,90,85,"<---", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,90,95,"<---", Font8x8);
    }
  else if ((TempRelay&(1<<6))==1<<6) 
    {
    ReefAngel.LCD.Clear(255,45,75,130,105);
    ReefAngel.LCD.DrawLargeText(0,255,5,75,"--->", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,5,85,"--->", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,5,95,"--->", Font8x8);
    }
  else
    { 
    ReefAngel.LCD.Clear(255,5,75,45,105);
    ReefAngel.LCD.Clear(255,45,75,130,105);
    ReefAngel.LCD.DrawLargeText(0,255,45,85," ~~~", Font8x8);
    }
  if ((TempRelay2&(1<<5))==1<<5)
  {
   ReefAngel.LCD.Clear(255,80,45,100,65);
   ReefAngel.LCD.DrawLargeText(0,255,40,45,"|", Font8x8);
   ReefAngel.LCD.DrawLargeText(0,255,40,55,"v", Font8x8);
  }
  else if ((TempRelay2&(1<<6))==1<<6) 
    {
   ReefAngel.LCD.Clear(255,40,45,60,65);
   ReefAngel.LCD.DrawLargeText(0,255,80,45,"|", Font8x8);
   ReefAngel.LCD.DrawLargeText(0,255,80,55,"v", Font8x8);
    }  
  else
    { 
   ReefAngel.LCD.Clear(255,40,45,100,65);
    }    
    break;
}
}
void receiveEvent(int howMany) 
{
    if (howMany==32)  // Our custom protocol is 13 bytes
  {
    byte cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10;
    byte cmd11,cmd12,cmd13,cmd14,cmd15,cmd16,cmd17,cmd18,cmd19,cmd20;
    byte cmd21,cmd22,cmd23,cmd24,cmd25,cmd26,cmd27,cmd28,cmd29,cmd30;
    byte cmd31,cmd32;
    cmd1=Wire.read();
    cmd2=Wire.read();
    cmd3=Wire.read();
    cmd4=Wire.read();
    cmd5=Wire.read();
    cmd6=Wire.read();
    cmd7=Wire.read();
    cmd8=Wire.read();
    cmd9=Wire.read();
    cmd10=Wire.read();
    cmd11=Wire.read();
    cmd12=Wire.read();
    cmd13=Wire.read();
    cmd14=Wire.read();
    cmd15=Wire.read();
    cmd16=Wire.read();
    cmd17=Wire.read();
    cmd18=Wire.read();
    cmd19=Wire.read();
    cmd20=Wire.read();
    cmd21=Wire.read();
    cmd22=Wire.read();
    cmd23=Wire.read();
    cmd24=Wire.read();
    cmd25=Wire.read();
    cmd26=Wire.read();
    cmd27=Wire.read();
    cmd28=Wire.read();
    cmd29=Wire.read();
    cmd30=Wire.read();
    cmd31=Wire.read();
    cmd32=Wire.read();   
   if (cmd1=='$' && cmd2=='$' && cmd3=='$') // the first 3 bytes of the custom protocol are $$$ to ensure it's coming from RA
    {
    maintemp=(cmd4<<8)+cmd5;
    sumptemp=(cmd6<<8)+cmd7;
    roomtemp=(cmd8<<8)+cmd9;
    ph=(cmd10<<8)+cmd11;
    wavetime=(cmd12<<8)+cmd13;
    moonlight=(cmd14<<8)+cmd15;
    level=cmd16;
    atos=cmd17;
    TempRelay=cmd18;
    TempRelay2=cmd19;
    flow0=(cmd20<<8)+cmd21;
    flow1=(cmd22<<8)+cmd23;
    flow2=(cmd24<<8)+cmd25;
    mhour=cmd26;
    mminute=cmd27;
    msecond=cmd28;
    mday=cmd29;
    mmonth=cmd30;
    myear=(cmd31<<8)+cmd32;
    }
  }
  else
    for (int a=0;a<howMany;a++)
      Wire.read(); // if the number of bytes is not 32, discard everything
  }