Automation.c

Fra Hougaard

Skift til: Navigation, Søgning
// AkvarieComputer - menu.c
 
#include <pic18.h>
#include <stdio.h>
#include <string.h>
#include "lcd.h"
#include "delay.h"
#include "akvarie.h"
#include "menu.h"
#include "xeeprom.h"
 
const char AutomationSelectType[] = "Type <%s>     ";
const char *AutomationSelectTexts[] = {AutomationSelectType};
const char AutomationSelectTypeTypes[] = {TYPE_AUTOMATION};
const void *AutomationSelectTypeValues[] = {&CA.Type};
extern const char *Automationtypes_values[];
 
const char DeleteAutomation[] = "<Delete Automation>";
 
const char Light_1[] =     "From (hour)  <%d> ";
const char Light_2[] =     "To   (hour)  <%d> ";
const char Light_3[] =     "Power        <%d> ";
const char *LightTexts[] = {Light_1,Light_2,Light_3,DeleteAutomation,NULL};
const void *LightData[] = {&CA.Data.Light.StartTime,&CA.Data.Light.StopTime,&CA.Data.Light.PowerNo};
const char LightTypes[] = {TYPE_INTEGER,TYPE_INTEGER,TYPE_INTEGER};
 
// just Light_3 // const char Osmolator_1[] = "Power   <%d> ";
const char Osmolator_2[] = "Input 1      <%s> ";
const char Osmolator_3[] = "Input 2      <%s> ";
const char *OsmolatorTexts[] = {Light_3,Osmolator_2,Osmolator_3,DeleteAutomation,NULL};
const void *OsmolatorData[] = {&CA.Data.Osmolator.PowerNo,&CA.Data.Osmolator.Input[0],&CA.Data.Osmolator.Input[1]};	
const char OsmolatorTypes[] = {TYPE_INTEGER,TYPE_POWER,TYPE_POWER};
 
const char Ozonizer_1[] =  "Max mV Level <%d> ";
const char *OzonizerTexts[] = {Ozonizer_1,Light_3,DeleteAutomation,NULL};
const void *OzonizerData[] = {&CA.Data.Ozonizer.RedoxMaxLevel,&CA.Data.Ozonizer.PowerNo};	
const char OzonizerTypes[] = {TYPE_INTEGER,TYPE_INTEGER};
 
const char CalciumReactor_1[]= "Cut-off pH <%.2f> ";
const char *CalciumReactorTexts[] = {CalciumReactor_1,Light_3,Light_1,Light_2,DeleteAutomation,NULL};
const void *CalciumReactorData[]= {&CA.Data.CalciumReactor.CutOffpH,
	                                 &CA.Data.CalciumReactor.PowerNo,
	                                 &CA.Data.CalciumReactor.StartTime,
	                                 &CA.Data.CalciumReactor.StopTime};
const char CalciumReactorTypes[] = {TYPE_FLOAT2,TYPE_INTEGER,TYPE_INTEGER,TYPE_INTEGER};
 
const char DosingPump_1[] = "Every <%d> hour   ";	
const char DosingPump_2[] = "Every <%d> minute ";	
const char DosingPump_3[] = "Run for <%d> sec. ";	
const char *DosingPumpTexts[] = {DosingPump_1,DosingPump_2,DosingPump_3,Light_3,DeleteAutomation,NULL};
const char *DosingPumpData[] = {&CA.Data.DosingPump.Hour,
	                             &CA.Data.DosingPump.Minute,
	                             &CA.Data.DosingPump.Seconds,
	                             &CA.Data.DosingPump.PowerNo};
const char DosingPumpTypes[] = {TYPE_INTEGER,TYPE_INTEGER,TYPE_INTEGER,TYPE_INTEGER};	                             
 
char ReadAutomation(int No)
{
	char Error;
 
	if (No > 255)
		ErrorMsg("Outofrange",155);
 
	Error = XEEReadArray(0xa0,No * 100,&CA,sizeof(Automation));
	if (Error == XEE_SUCCESS)
		return 1;
	else
	{
		ErrorMsg("EEPROM Error",200+Error);
		return 0;
	}
}
 
char WriteAutomation(int No)
{
	char 	i;
	char 	Error;
	char  *Pointer = &CA;
	XEEBeginWrite(0xa0,No * 100);
	for (i = 0; i < sizeof(Automation); i++)
	{
		Error = XEEWrite(*Pointer++);
		if (Error != XEE_SUCCESS)
			ErrorMsg("EEPROM Write",210+Error);
	}
	XEEEndWrite();
}
 
char GetAutomationType()
{
	char i = 0;
	while(Automationtypes_values[i])
	{
		if (strcmp(Automationtypes_values[i],CA.Type) == 0)
			return i;
		i++;
	}
	return -1;
}
 
void InitAutomation(int No)
{
	memset(&CA,0,sizeof(Automation));
	CA.MagicChar = MAGICCHAR;
	CA.No = No;
	strcpy(CA.Type,"Off");
}
 
char DeleteAutomationFunc(int No)
{
	char i;
	char Last;
	char Text[30];
	lcd_clear();
	sprintf(Text,"Delete %s ?",CA.Type);
	lcdtext(1,1,Text);
	while(1)
	{
		if (KeyEnter)
		{
			while(KeyEnter);
			i = No + 1;
			while(1)
			{
				DelayMs(10);
				ReadAutomation(i);
				if (CA.MagicChar == MAGICCHAR)
				{
					CA.No = CA.No - 1;
					DelayMs(10);
					WriteAutomation(CA.No);
					i++;
				}
				else
				{
					// Delete Last
					CA.MagicChar = 0;
					CA.No = i - 1;
					DelayMs(10);
					WriteAutomation(CA.No);
					sprintf(Text,"Deleted no. %d",CA.No);
					return 1;
				}
			}
		}
		if (KeyLeft)
		{
			while(KeyLeft);
			return 0;
		}
	}
}
 
void EditAutomation(int No)
{
	char OneUp;
	ReadAutomation(No);
	if (CA.MagicChar == MAGICCHAR)
	{
		switch(GetAutomationType())
		{
			case 0: // Off
				break;
			case 1: // Light
				OneUp = 0;
				while(!OneUp)
				{
					switch(OpenMenu(LightTexts,LightData,LightTypes))
					{
						case 0: // Start Time
						case 1: // Stop Time
						case 2: // Power
							if (EditOption(LightTexts,LightData,LightTypes,-1,0))
								WriteAutomation(CA.No);
							break;
						case 3: // Delete automation
							DeleteAutomationFunc(CA.No);
							OneUp = 1;
							break;
						case -1:
							OneUp = 1;
							break;
					}
				}
				break;
			case 2: // Osmolator
				OneUp = 0;
				while(!OneUp)
				{
					switch(OpenMenu(OsmolatorTexts,OsmolatorData,OsmolatorTypes))
					{
						case 0: // Start Time
						case 1: // Stop Time
						case 2: // Power
							if (EditOption(OsmolatorTexts,OsmolatorData,OsmolatorTypes,-1,0))
								WriteAutomation(CA.No);
							break;
						case 3: // Delete automation
							DeleteAutomationFunc(CA.No);
							OneUp = 1;
							break;
						case -1:
							OneUp = 1;
							break;
					}
				}
				break;
			case 3: // Ozonizer
				OneUp = 0;
				while(!OneUp)
				{
					switch(OpenMenu(OzonizerTexts,OzonizerData,OzonizerTypes))
					{
						case 0: // Max Redox Level
						case 1: // Power
							if (EditOption(OzonizerTexts,OzonizerData,OzonizerTypes,-1,0))
								WriteAutomation(CA.No);
  						break;
						case 2: // Delete automation
							DeleteAutomationFunc(CA.No);
							OneUp = 1;
							break;
						case -1:
							OneUp = 1;
							break;
 					}	
				}
				break;
			case 4: // Calcium Reactor
				OneUp = 0;
				while(!OneUp)
				{
					switch(OpenMenu(CalciumReactorTexts,CalciumReactorData,CalciumReactorTypes))
					{
						case 0: // Cut off pH
						case 1: // Power
						case 2: // Starttime
						case 3: // stoptime
							if (EditOption(CalciumReactorTexts,CalciumReactorData,CalciumReactorTypes,-1,0))
								WriteAutomation(CA.No);
							break;
						case 4:
							DeleteAutomationFunc(CA.No);
							OneUp = 1;
							break;
						case -1:
							OneUp = 1;
							break;
					}
				}
			  break;
			case 5: // Dosing Pump
				OneUp = 0;
				while(!OneUp)
				{
					switch(OpenMenu(DosingPumpTexts,DosingPumpData,DosingPumpTypes))
					{
						case 0:
						case 1:
						case 2:
						case 3:
							if (EditOption(DosingPumpTexts,DosingPumpData,DosingPumpTypes,-1,0))
								WriteAutomation(CA.No);
							break;
						case 4:
							DeleteAutomationFunc(CA.No);
							OneUp = 1;
							break;
						case -1:
							OneUp = 1;
							break;
					}
				}
			  break;
			default: // Unknown automation - delete it !
				DeleteAutomationFunc(CA.No);
				break;
		}
	}
}
 
void NewAutomation()
{
	char Text[30];
	int No = 1;
	if (ReadAutomation(No))
	{
		while (CA.MagicChar == MAGICCHAR && No < 255)
		{
		  No++;
		  ReadAutomation(No);
		}
	}
	if (No == 255)
	{
		ErrorMsg("Out of memory",22);
	}
	lcd_clear();
	sprintf(Text,"New Automation(%d)",No);
	lcdtext(1,1,Text);
	InitAutomation(No);
	if (EditOption(AutomationSelectTexts,AutomationSelectTypeValues,(char*)AutomationSelectTypeTypes,2,0))
	{
		// Init values
		switch(GetAutomationType())
		{
			case 0:
				lcd_clear();
			  return;
			  break;
			case 1: // Light
				CA.Data.Light.StartTime = 0;
				CA.Data.Light.StopTime = 23;
				CA.Data.Light.PowerNo = 0;
			  break;
			case 2: // Osmolator
				CA.Data.Osmolator.PowerNo = 0;
				break;
			case 3: // Ozonizer
  			CA.Data.Ozonizer.RedoxMaxLevel = 300;
	  		CA.Data.Ozonizer.PowerNo = 0;
			  break;
			case 4: // Calcium Reactor
  			CA.Data.CalciumReactor.CutOffpH = 6.5f;
				CA.Data.CalciumReactor.PowerNo = 0;
				CA.Data.CalciumReactor.StartTime = 12;
				CA.Data.CalciumReactor.StopTime = 23;
				break;
			case 5: // Dosing Pump
				CA.Data.DosingPump.Hour = 0;
				CA.Data.DosingPump.Minute = 0;
				CA.Data.DosingPump.Seconds = 0;
				CA.Data.DosingPump.PowerNo = 0;
				break;
		}
		WriteAutomation(No);
		lcd_clear();
		sprintf(Text,"Created as no. %d",No);
		lcdtext(1,1,Text);
		lcdtext(1,2,"Press Enter..");
		while(!KeyEnter);
		while(KeyEnter);
	}
}
 
void PerformAutomation()
{
	char	Text[30];
	char 	No;
	char	d;
 
	// Loop Through Automation
	for (No = 1; No < 255; No++)
	{
		if (ReadAutomation(No))
		{
			if (CA.MagicChar == MAGICCHAR)
			{
				for (d = 0; d < 50; d++)
				{
					DelayMs(5);
					if (KeyEnter)
						return;
				}
				switch(GetAutomationType())
				{
					case -1:
						lcdtext(1,4,"Unknown automation");
						DelayMs(250);
						break;
					case 0: // Off
						break;
					case 1: // Light
						sprintf(Text,"Auto: %d %s      ",CA.No,CA.Type);
						lcdtext(1,4,Text);
					  if (CA.Data.Light.StartTime > CA.Data.Light.StopTime)
					  {
						  // Over midnat
							if (AI.Clock[2] >= CA.Data.Light.StartTime ||
							    AI.Clock[2] < CA.Data.Light.StopTime)
							{
							  if (CA.Data.Light.PowerNo >=1 && CA.Data.Light.PowerNo <= 4)
								  strcpy(AI.Power[CA.Data.Light.PowerNo - 1],"On");
							}
							else
							  if (CA.Data.Light.PowerNo >=1 && CA.Data.Light.PowerNo <= 4)
								  strcpy(AI.Power[CA.Data.Light.PowerNo - 1],"Off");
						}
						else
							if (AI.Clock[2] >= CA.Data.Light.StartTime &&
							    AI.Clock[2] < CA.Data.Light.StopTime)
							{
							  if (CA.Data.Light.PowerNo >=1 && CA.Data.Light.PowerNo <= 4)
								  strcpy(AI.Power[CA.Data.Light.PowerNo - 1],"On");
							}
							else
							  if (CA.Data.Light.PowerNo >=1 && CA.Data.Light.PowerNo <= 4)
								  strcpy(AI.Power[CA.Data.Light.PowerNo - 1],"Off");
					  break;
					case 2: // Osmolator
						{
							char Result[2] = {0,0};
							char i;
							sprintf(Text,"Auto: %d %s      ",CA.No,CA.Type);
							lcdtext(1,4,Text);
							for (i = 0; i < 2; i++)
							{
								if (strcmp(CA.Data.Osmolator.Input[i],"Void\0") != 0)
								{
									if (strcmp(CA.Data.Osmolator.Input[i],"On\0") == 0)
									{
										if (i == 0)
										{
											if (RA4 == 1)
												Result[i] = 1;
											else
												Result[i] = 0;
									  }
									  if (i == 1)
										{
											if (RA5 == 1)
												Result[i] = 1;
											else
												Result[i] = 0;
									  }
									}
									if (strcmp(CA.Data.Osmolator.Input[i],"Off\0") == 0)
									{
										if (i == 0)
										{
											if (RA4 == 0)
												Result[i] = 1;
											else
												Result[i] = 0;
										}
										if (i == 1)
										{
											if (RA5 == 0)
												Result[i] = 1;
											else
												Result[i] = 0;
										}
									}
								}
								else
									Result[i] = 1;
							}				
							if (Result[0] && Result[1])
								strcpy(AI.Power[CA.Data.Osmolator.PowerNo - 1],"On");
							else
								strcpy(AI.Power[CA.Data.Osmolator.PowerNo - 1],"Off");
						}
						break;
					case 3: // Ozonizer
						{
							char i;
							sprintf(Text,"Auto: %d %s      ",CA.No,CA.Type);
							lcdtext(1,4,Text);
							for (i = 0; i < 4; i++)
							{
								if (strcmp(AI.ProbeSetup[i],"mV\0") == 0)
								{
									if (AI.Probe[i] < CA.Data.Ozonizer.RedoxMaxLevel)
										strcpy(AI.Power[CA.Data.Ozonizer.PowerNo - 1],"On");
									else
										strcpy(AI.Power[CA.Data.Ozonizer.PowerNo - 1],"Off");
								}
							}
						}
						break;
					case 4: // Calcium Reactor
						{
							char i;
							sprintf(Text,"Auto: %d %s      ",CA.No,CA.Type);
							lcdtext(1,4,Text);
							for (i = 0; i < 4; i++)
							{
								if (strcmp(AI.ProbeSetup[i],"pH\0") == 0)
								{
									if (strcmp(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"On\0") == 0)
									{
										if (AI.Probe[i] < CA.Data.CalciumReactor.CutOffpH)
											strcpy(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"Off");
										else
											strcpy(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"On");
									}
									else
									{										
										if (AI.Probe[i] < (CA.Data.CalciumReactor.CutOffpH + 0.2))
											strcpy(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"Off");
										else
											strcpy(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"On");
									}
								}
							}
  					  if (CA.Data.CalciumReactor.StartTime > CA.Data.CalciumReactor.StopTime)
  					  {
  						  // Over midnat
  							if (AI.Clock[2] >= CA.Data.CalciumReactor.StartTime ||
  							    AI.Clock[2] < CA.Data.CalciumReactor.StopTime)
  							{
	  							// Nothing !
  							}
  							else
  							  if (CA.Data.CalciumReactor.PowerNo >=1 && CA.Data.CalciumReactor.PowerNo <= 4)
  								  strcpy(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"Off");
  						}
  						else
  							if (AI.Clock[2] >= CA.Data.CalciumReactor.StartTime &&
  							    AI.Clock[2] < CA.Data.CalciumReactor.StopTime)
  							{
	  							// Nothing !
  							}
  							else
  							  if (CA.Data.CalciumReactor.PowerNo >=1 && CA.Data.CalciumReactor.PowerNo <= 4)
  								  strcpy(AI.Power[CA.Data.CalciumReactor.PowerNo - 1],"Off");						
						}
						break;
					case 5: // Dosing Pump
						{
							if (AI.Clock[2] % CA.Data.DosingPump.Hour == 0)
							{
								// Hour OK
								if (AI.Clock[1] % CA.Data.DosingPump.Minute == 0)
								{
									// Minute OK
									if (AI.Clock[0] < CA.Data.DosingPump.Seconds)
  								  strcpy(AI.Power[CA.Data.DosingPump.PowerNo - 1],"On");						
  								else  
  								  strcpy(AI.Power[CA.Data.DosingPump.PowerNo - 1],"Off");						
 
								}								
							}
						}
						break;	
				}
			}
			else
			{
				UpdatePowers();
				for (d = 0; d < 50; d++)
				{
					DelayMs(5);
					if (KeyEnter)
						return;
				}
				lcdtext(1,4,"                    ");
				return;
			}
		}
	}
}
Personlige værktøjer