/****************************************************************************
 Title	:	TERMINAL FOR VISUALIZATION AND CONTROL CONDITIONS IN HOUSE
 Author	:	Patrik Szalay <xszala01@stud.feec.vutbr.cz>
 File	:	regulation.c
 Software:	CodeWarrior Development Studio Version: 10.6 Build Id:140329
 Target	:	MC9S08LH64

 DESCRIPTION
       Regulation algorithms

 USAGE
       
*****************************************************************************/
#include "regulation.h"

decimal Room_Temp, Water_Out_Temp, Water_Return_Temp, OutDoor_Temp, OutDoor_Hum;
bool Heater = false, Pump = false, HeatingEnabled = false, AutoSwitchingEnabled = true, systTypeGas = true;
decimal RegulateToDayTemp = 2100;
decimal RegulateToNightTemp = 1900;
decimal RegulateToTemp;
decimal RegulationHyst = 100;
decimal WaterDiff = 1500;
decimal RegulateToMaxWaterTemp = 6500;
decimal WaterDiffHyst = 1000;
decimal OnAverageTemp = 1300;
decimal OffAverageTemp = 1600;
decimal AverageTemp = NOT_MEASURED_VALUE;
int dayTempStart = 6, dayTempEnd = 23;
byte dayState = DAY;

typedef struct Averages{
	decimal day1[3];
	decimal day2[3];
	decimal avg2days[2];
	decimal average;
}Averages;

Averages TempAverages;
int measTime = 0, measDay = 0;
byte pumpDelayTime = 5;
int pumpDelayTimer = 0;
bool pumpEnable, pumpDelayEnable;

void InitAverages(void)
{
	TempAverages.day1[0] = NOT_MEASURED_VALUE;
	TempAverages.day1[1] = NOT_MEASURED_VALUE;
	TempAverages.day1[2] = NOT_MEASURED_VALUE;
	TempAverages.day2[0] = NOT_MEASURED_VALUE;
	TempAverages.day2[1] = NOT_MEASURED_VALUE;
	TempAverages.day2[2] = NOT_MEASURED_VALUE;
	TempAverages.avg2days[0] = NOT_MEASURED_VALUE;
	TempAverages.avg2days[1] = NOT_MEASURED_VALUE;
	TempAverages.average = NOT_MEASURED_VALUE;
	measDay = 1;
}

decimal getRoom_Temp(void)
{
	return Room_Temp;
}
void setRoom_Temp(decimal value)
{
	Room_Temp = value;
}

decimal getOutDoor_Temp(void)
{
	return OutDoor_Temp;
}
void setOutDoor_Temp(decimal value)
{
	OutDoor_Temp = value;
}

decimal getOutDoor_Hum(void)
{
	return OutDoor_Hum;
}
void setOutDoor_Hum(decimal value)
{
	OutDoor_Hum = value;
}

decimal getWater_Out_Temp(void)
{
	return Water_Out_Temp;
}
void setWater_Out_Temp(decimal value)
{
	Water_Out_Temp = value;
}

decimal getWater_Return_Temp(void)
{
	return Water_Return_Temp;
}
void setWater_Return_Temp(decimal value)
{
	Water_Return_Temp = value;
}

decimal getRegulateToTemp(void)
{
	return RegulateToTemp;
}

decimal getRegulateToDayTemp(void)
{
	return RegulateToDayTemp;
}
void setRegulateToDayTemp(decimal value)
{
	RegulateToDayTemp = value;
}

decimal getRegulateToNightTemp(void)
{
	return RegulateToNightTemp;
}
void setRegulateToNightTemp(decimal value)
{
	RegulateToNightTemp = value;
}

decimal getRegulateToMaxWaterTemp(void)
{
	return RegulateToMaxWaterTemp;
}
void setRegulateToMaxWaterTemp(decimal value)
{
	RegulateToMaxWaterTemp = value;
}

decimal getRegulationHyst(void)
{
	return RegulationHyst;
}
void setRegulationHyst(decimal value)
{
	RegulationHyst = value;
}

decimal getWaterDiff(void)
{
	return WaterDiff;
}
void setWaterDiff(decimal value)
{
	WaterDiff = value;
}

decimal getWaterDiffHyst(void)
{
	return WaterDiffHyst;
}
void setWaterDiffHyst(decimal value)
{
	WaterDiffHyst = value;
}

byte getPumpDelayTime(void)
{
	return pumpDelayTime;
}
void setPumpDelayTime(byte value)
{
	pumpDelayTime = value;
}

bool getHeater_State(void)
{
	return Heater;
}
void setHeater_State(bool state)
{
	Heater = state;
}

bool getPump_State(void)
{
	return Pump;
}
void setPump_State(bool state)
{
	Pump = state;
}

decimal getAverageTemp(void)
{
	if(AverageTemp != NOT_MEASURED_VALUE)
	{
		return AverageTemp;
	}
	else
	{
		return measure(HTU21D_TEMP);
	}
}

void setAVGTemp(decimal value)
{
	AverageTemp = value;
}
void setAverageTemp(void)
{
	decimal temp = 0, value;
	byte count = 0;
	
	value = measure(HTU21D_TEMP);
	if(clock_now.hours == 7 && measTime != clock_now.hours)
	{
		if(measDay == 1)
		{
			TempAverages.day1[0] = value;
		}
		else if(measDay == 2)
		{
			TempAverages.day2[0] = value;
		}
		measTime = 7;
	}
	else if(clock_now.hours == 14 && measTime != clock_now.hours)
	{
		if(measDay == 1)
		{
			TempAverages.day1[1] = value;
		}
		else if(measDay == 2)
		{
			TempAverages.day2[1] = value;
		}
		measTime = 14;
	}
	else if(clock_now.hours == 21 && measTime != clock_now.hours)
	{
		if(measDay == 1)
		{
			TempAverages.day1[2] = value;
			measDay = 2;
		}
		else if(measDay == 2)
		{
			TempAverages.day2[2] = value;
			measDay = 1;
		}
		measTime = 21;
	}
	if(TempAverages.day1[0] != NOT_MEASURED_VALUE)
	{
		temp += TempAverages.day1[0];
		count++;
	}
	if(TempAverages.day1[1] != NOT_MEASURED_VALUE)
	{
		temp += TempAverages.day1[1];
		count++;
	}
	if(TempAverages.day1[2] != NOT_MEASURED_VALUE)
	{
		temp += TempAverages.day1[2]*2;
		count += 2;
	}
	if(TempAverages.day2[0] != NOT_MEASURED_VALUE)
	{
		temp += TempAverages.day2[0];
		count++;
	}
	if(TempAverages.day2[1] != NOT_MEASURED_VALUE)
	{
		temp += TempAverages.day2[1];
		count++;
	}
	if(TempAverages.day2[2] != NOT_MEASURED_VALUE)
	{
		temp += TempAverages.day2[2]*2;
		count += 2;
	}
	if(count > 0)
	{
		AverageTemp = temp / count;
	}
	else
	{
		AverageTemp = value;
	}
		
}

int getDayTempStart(void)
{
	return dayTempStart;
}
void setDayTempStart(int value)
{
	dayTempStart = value;
}

int getDayTempEnd(void)
{
	return dayTempEnd;
}
void setDayTempEnd(int value)
{
	dayTempEnd = value;
}

bool getSystType(void)
{
	return systTypeGas;
}
void setSystType(bool value)
{
	systTypeGas = value;
}

decimal getOnAverageTemp(void)
{
	return OnAverageTemp;
}
void setOnAverageTemp(decimal value)
{
	OnAverageTemp = value;
}

decimal getOffAverageTemp(void)
{
	return OffAverageTemp;
}
void setOffAverageTemp(decimal value)
{
	OffAverageTemp = value;
}

bool getAutoSwitchingState(void)
{
	return AutoSwitchingEnabled;
}
void setAutoSwitchingState(bool value)
{
	AutoSwitchingEnabled = value;
}

void setRegulateToTemp(void)
{
	if(clock_now.hours >= dayTempStart && clock_now.hours < dayTempEnd)
	{
		RegulateToTemp = RegulateToDayTemp;
		dayState = DAY;
	}
	else
	{
		RegulateToTemp = RegulateToNightTemp;
		dayState = NIGHT;
	}
}

byte getDayState(void)
{
	return dayState;
}


void setHeating(void)
{
	if(AutoSwitchingEnabled)
	{
		
		if(clock_now.month >= 9 || clock_now.month <6)
		{
			if(AverageTemp < OnAverageTemp)
			{
				HeatingEnabled = true;
			}
			else if(AverageTemp > OffAverageTemp)
			{
				HeatingEnabled = false;
			}
		}
		else
		{
			HeatingEnabled = false;
		}
	}
	else
	{
		HeatingEnabled = true;
	}
	setRegulateToTemp();
}

void Thermostat(void)
{	
	setHeating();
	if(HeatingEnabled)
	{
		if(systTypeGas)
		{
			if (Heater && ((Room_Temp > (RegulateToTemp + RegulationHyst/2)) || (Water_Out_Temp > (RegulateToMaxWaterTemp + maxWaterTempHyst/2))))
			{
				setHeater_State(false);
				pumpEnable = false;
				pumpDelayEnable = true;
			}
			else if(~Heater && ((Room_Temp <= (RegulateToTemp - RegulationHyst/2)) && (Water_Out_Temp <= (RegulateToMaxWaterTemp - maxWaterTempHyst/2))))
			{
				setHeater_State(true);
				pumpEnable = true;
			}
		}
		else
		{
			if(Room_Temp <= (RegulateToTemp - RegulationHyst/2))
			{
				pumpEnable = true;
			}
			else if(Room_Temp > (RegulateToTemp + RegulationHyst/2))
			{
				pumpEnable = false;
				pumpDelayEnable = true;
			}
		}
		
		if (~Pump && ((Water_Out_Temp - Water_Return_Temp >= WaterDiff + WaterDiffHyst/2) || (Water_Out_Temp - Water_Return_Temp <= WaterDiff - WaterDiffHyst/2)) && (pumpEnable || pumpDelayEnable) )
		{
			setPump_State(true);
		}
		else if (Pump && ((Water_Out_Temp - Water_Return_Temp < WaterDiff + WaterDiffHyst/2) && (Water_Out_Temp - Water_Return_Temp > WaterDiff - WaterDiffHyst/2)) && pumpEnable)
		{
			pumpDelayEnable = true;
		}
		else if (!(pumpEnable || pumpDelayEnable))
		{
			setPump_State(false);
		}
	}
	else
	{
		if(Heater)
		{
			setHeater_State(false);
			pumpEnable = false;
			pumpDelayEnable = true;
		}
		if (!(pumpEnable || pumpDelayEnable))
		{
			setPump_State(false);
		}
	}
	
	if(~Pump && (Water_Out_Temp >= RegulateToMaxWaterTemp))
	{
		setPump_State(true);
		setHeater_State(false);
	}
	if(~Heater && (Room_Temp <= ROOMTEMP_MIN))
	{
		setHeater_State(true);
		setPump_State(true);
	}
	if(Heater)
	{
		setPump_State(true);
	}
	
	
}

