//#include <p18f258.h>
#include <p18f2420.h>
#include <math.h>
#include <conio.h>
#include <stdio.h>

#define	lcd_data	PORTC
#define	lcd_rs		PORTCbits.RC0
#define	lcd_rw		PORTCbits.RC1
#define	lcd_e		PORTCbits.RC3
#define	Button1		PORTBbits.RB3
#define	Button2		PORTBbits.RB2
#define	Button3		PORTBbits.RB1
#define	Button4		PORTBbits.RB0


void Delay(unsigned int);
void WriteLcd(char);
void PositionLcd(unsigned char);
void InitLcd(void);
void ClearLcd(void);
void WriteDec(int , unsigned char);
void Boot(void);
void InterruptHandlerHigh (void);
void LoadData(void);

void WriteEEProm(unsigned char, unsigned char);
unsigned char ReadEEProm(unsigned char);
unsigned int AdConv(void);

/*
EEPROM

00		Pointer
01	02	Temperature1
03	04	Temperature2
05	06	Temperature3

*/


unsigned char		i, mTimer = 0, mTimer2 = 0, mTimer3 = 0, EepromData, EepromAddres, Counter = 1, PwmData,
					temp1, temp2, temp3, temp4, Pointer, adl, adh, portb, lb, hb, Plus, Minus;

unsigned int		 ihighl = 0, setpoint = 300, T1, T2, T3;

int					temperature, temp, test, power;
float				m = 0.7998037 ,b = 19.267255, P = 2.0, I = 0.08, D = 0.05,
					dT = 0.1, error = 0, dI = 0, dD = 0, varP, varI, varD, varE = 0,
					varPWM, varTEMP; 

struct {
  unsigned Pwm:1;
  unsigned Display:1;
  unsigned Button:1;
  unsigned TimeOut:1;
  unsigned NU2:1;
  unsigned NU3:1;
  unsigned NU4:1;
  unsigned NU5:1;
}Control;	



void main(void)
{
	Boot();
	while(1)
	{
		if(PORTB != 15)Control.Button = 1;
		if(Control.Pwm == 1)
		{
			AdConv();
			ihighl = ((setpoint - 50) / 2.6);
			if(setpoint >= 400)ihighl += 10;
			varTEMP = (((float)adh * 255) + (float)adl);
			temperature = (unsigned int)((varTEMP * m) - b);
			Control.Pwm = 0;
			error = ((float)setpoint - (float)temperature);
			varP = P * error;
			varI += (dT * error * I);
			if(varI < 0)varI = 0;
			if(varI > ihighl)varI = (float)ihighl;
			varD = (((error - varE)/dT) * D);
			varPWM = varP + varI + varD;
			if(varPWM < 0)varPWM = 0;
			if(varPWM > 255)varPWM = 255;
			CCPR1L =  varPWM;
			if(error < -100)error = -100;
			if(error > 100)error = 100;
			varE = error;
		}
		
		if(Control.Display == 1)
		{
			Control.Display = 0;
			PositionLcd(0x02);
			WriteDec(((unsigned int)CCPR1L * 100 )/ 255,2);
			if(temperature >= 500)
			{
				PositionLcd(11);
				WriteLcd('-');
				WriteLcd('-');
				WriteLcd('-');
			}
			else
			{
				PositionLcd(11);
				WriteLcd(' ');
				WriteLcd(' ');
				WriteDec(temperature,11);
			}			
		}

		if(Control.Button == 1)
		{
			Control.Button = 0;
			if(!Button1)
			{
				if(Pointer != 1)
				{
					setpoint = T1;
					PositionLcd((Pointer * 4)+0x3F);
					WriteLcd(' ');
					Pointer = 1;
					PositionLcd(0x43);
					WriteLcd(0x7F);
					WriteEEProm(1,0);
					while(!Button1);
				}
			}
			else if(!Button2)
			{
				if(Pointer != 2)
				{
					setpoint = T2;
					PositionLcd((Pointer * 4)+0x3F);
					WriteLcd(' ');
					Pointer = 2;
					PositionLcd(0x47);
					WriteLcd(0x7F);
					WriteEEProm(2,0);
					while(!Button2);
				}
			}
			else if(!Button3)
			{
				if(Pointer != 3)
				{
					setpoint = T3;
					PositionLcd((Pointer * 4)+0x3F);
					WriteLcd(' ');
					Pointer = 3;
					PositionLcd(0x4B);
					WriteLcd(0x7F);
					WriteEEProm(3,0);
					while(!Button3);
				}
			}
			else if(!Button4)
			{
				INTCONbits.GIE = 0;
				CCPR1L = 0;
				ClearLcd();
				WriteLcd('T');
				WriteLcd('=');
				WriteDec(setpoint,0x02);
				PositionLcd(0x05);
				WriteLcd(0b11011111);		//°
				WriteLcd(0b01000011);		//C
				PositionLcd(0x42);
				WriteLcd('-');
				PositionLcd(0x46);
				WriteLcd('+');
				PositionLcd(0x49);
				WriteLcd('E');
				WriteLcd('s');
				WriteLcd('c');
				PositionLcd(0x4E);
				WriteLcd('O');
				WriteLcd('K');
				while(Button3 & Button4)
				{
					Plus = 0;Minus =0;
					if(!Button1)
					{
							while(!Button1)
						{
							setpoint--;
							Minus++;
							if(Minus >= 10)
							{
								setpoint -= 9;
								Minus = 10;
							}
							if(setpoint > 450)setpoint = 450;
							if(setpoint < 1)setpoint = 0;
							PositionLcd(0x02);
							WriteLcd(' ');
							WriteLcd(' ');
							WriteLcd(' ');
							WriteDec(setpoint,0x02);
							Delay(65535);
						}
					}
					if(!Button2)
					{
						while(!Button2)
						{
							setpoint++;
							Plus++;
							if(Plus >= 10)
							{
								setpoint += 9;
								Plus = 10;
							}
							if(setpoint > 450)setpoint = 450;
							if(setpoint < 1)setpoint = 0;
							PositionLcd(0x02);
							WriteLcd(' ');
							WriteLcd(' ');
							WriteLcd(' ');
							WriteDec(setpoint,0x02);
							Delay(65535);
						}
					}	
				}
				if(!Button4)
				{
					_asm
					movff	setpoint,lb	
					movff	setpoint+1,hb	
					_endasm
					WriteEEProm(lb,((Pointer*2)-1));
					WriteEEProm(hb,(Pointer*2));
					if(Pointer == 1)T1 = setpoint;
					else if(Pointer == 2)T2 = setpoint;
					else if(Pointer == 3)T3 = setpoint;
				}	
				
				
				ClearLcd();
				WriteLcd('P');
				WriteLcd('=');
				WriteDec(CCPR1L * 100 / 255,2);
				PositionLcd(5);
				WriteLcd('%');
				PositionLcd(9);
				if(temperature >= 500)
				{
					PositionLcd(11);
					WriteLcd('-');
					WriteLcd('-');
					WriteLcd('-');
				}
				else
				{
					WriteDec(temperature,11);
				}
				PositionLcd(14);
				WriteLcd(0b11011111);		//°
				WriteLcd(0b01000011);		//C
				T2CONbits.TMR2ON = 1;
				LoadData();
				WriteDec(T1,0x40);
				WriteDec(T2,0x44);
				WriteDec(T3,0x48);
				PositionLcd(0x4C);
				WriteLcd(' ');
				WriteLcd('S');
				WriteLcd('e');
				WriteLcd('t');
				PositionLcd((Pointer * 4)+0x3F);
				WriteLcd(0x7F);
				INTCONbits.GIE = 1;
			}
		}
	}
}


void Boot (void)
{
	ADCON0 = 0b10001001;		//AD converter
	ADCON1 = 0b11000100;
	TRISA = 0xFF;

	TRISB = 0b11111111;			//Key pad
	
	TRISC = 0;					//LCD communication port & PWM prot
	PORTC = 0x00;

	T2CON = 0b00100000;			//Timer 2
	
	CCP1CON =0b00001111; 		//PWM initialization. 1.22kHz
	CCPR1L = 0;					//0% duty cycle
	PR2 = 0xFF;					//8 bit resolution

	WriteEEProm(0x01,6);
	AdConv();
	varTEMP = (((float)adh * 255) + (float)adl);
	temperature = (unsigned int)((varTEMP * m) + b);
	InitLcd();					//LCD initialization
	ClearLcd();
	WriteLcd('P');
	WriteLcd('=');
	WriteDec(CCPR1L * 100 / 255,2);
	PositionLcd(5);
	WriteLcd('%');
	PositionLcd(9);
	if(temperature >= 500)
	{
		PositionLcd(11);
		WriteLcd('-');
		WriteLcd('-');
		WriteLcd('-');
	}
	else
	{
		WriteDec(temperature,11);
	}
	PositionLcd(14);
	WriteLcd(0b11011111);		//°
	WriteLcd(0b01000011);		//C
	T2CONbits.TMR2ON = 1;
	LoadData();
	WriteDec(T1,0x40);
	WriteDec(T2,0x44);
	WriteDec(T3,0x48);
	PositionLcd(0x4C);
	WriteLcd(' ');
	WriteLcd('S');
	WriteLcd('e');
	WriteLcd('t');
	PositionLcd((Pointer * 4)+0x3F);
	WriteLcd(0x7F);
	
//	TXSTA = 0b00000100;			//Init seial port
//	RCSTA = 0b10000000;
//	SPBRG = 0x0A;				//The baudrate is 115200
//	RCSTAbits.CREN = 1;			//Enable serial recver modul
//	TXSTAbits.TXEN = 1;

	INTCONbits.GIE = 1;			//Interrupts
	INTCONbits.PEIE = 1;
	PIE1bits.TMR2IE = 1;
	return;
}


void InitLcd(void)
{
	PORTC = 0b00110000;			//DL=1 8 bit interface
	lcd_e = 1;
	Delay(65535);
	lcd_e = 0;
	PORTC = 0b00110000;			//DL=1 8 bit interface
	lcd_e = 1;
	Delay(1024);
	lcd_e = 0;
	PORTC = 0b00110000;			//DL=1 8 bit interface
	lcd_e = 1;
	Delay(65535);
	lcd_e = 0;
	PORTC = 0b00100000;			//DL=1 4 bit interface
	lcd_e = 1;
	Delay(255);
	lcd_e = 0;
	PORTC = 0b00100000;			//DL=1 4 bit interface
	lcd_e = 1;
	Delay(255);
	lcd_e = 0;
	PORTC = 0b10000000;			//N=1  2 line display
	lcd_e = 1;					//F=0  5x7 dot matrix
	Delay(255);
	lcd_e = 0;

	PORTC = 0b00000000;				
	lcd_e = 1;
	Delay(255);
	lcd_e = 0;
	PORTC = 0b11000000;			 //D,C,B 
	lcd_e = 1;					  
	Delay(255);			
	lcd_e = 0;

	PORTC = 0b00000000;			//Clear LCD
	lcd_e = 1;
	Delay(255);
	lcd_e = 0;
	PORTC = 0b00010000;
	lcd_e = 1;		
	Delay(255);		
	lcd_e = 0;
	Delay(65535);	
	
	PORTC = 0b00000000;
	lcd_e = 1;
	Delay(255);
	lcd_e = 0;
	PORTC = 0b01100000;			//I/D=1 Increment counter
	lcd_e = 1;					//S=1   Automatic display shift
	Delay(255);
	lcd_e = 0;
	return;
}


void ClearLcd(void)
{
	PORTC = 0b00000000;			//Clear LCD
	lcd_e = 1;
	Delay(20);
	lcd_e = 0;
	PORTC = 0b00010000;
	lcd_e = 1;		
	Delay(20);		
	lcd_e = 0;
	Delay(65535);	
	return;
}


void WriteLcd(char data)
{
	unsigned char data_low, data_high;
	temp1 = data;
	_asm
		swapf	temp1,0,1
		movwf	temp2,1
		movlw	0xf0
		andwf	temp1,1,1
		andwf	temp2,1,1
		bsf		temp1,0,1
		bsf		temp2,0,1
	_endasm	
	data_high=temp1;
	data_low=temp2;
	PORTC = data_high;
	lcd_e = 1;
	Delay(20);
	lcd_e = 0;
	PORTC = data_low;
	lcd_e = 1;
	Delay(20);
	lcd_e = 0;
	lcd_rs = 0;
	Delay(20);
	return;
}


void PositionLcd(unsigned char position)
{
	unsigned char data_low, data_high;

	position += 128;

	temp1 = position;
	_asm
		swapf	temp1,0,1
		movwf	temp2,1
		movlw	0xf0
		andwf	temp1,1,1
		andwf	temp2,1,1
	_endasm	
	data_high=temp1;
	data_low=temp2;
	PORTC = data_high;
	lcd_e = 1;
	Delay(20);
	lcd_e = 0;
	PORTC = data_low;
	lcd_e = 1;
	Delay(20);
	lcd_e = 0;
	Delay(20);
	return;
}


void WriteDec(int value , unsigned char position)
{
	char temp, counter;

	counter = 3;
	PositionLcd(position);
	WriteLcd(' ');
	WriteLcd(' ');
	WriteLcd(' ');
	if (value == 0)
		{
		counter--;
		PositionLcd((counter + position));
		WriteLcd('0');
		return;
		}

	while (value)
		{
		counter--;
		PositionLcd((counter + position));
		temp = value % 10;
		value /= 10;
		WriteLcd((temp+48));
		}
	return;
}


unsigned int AdConv(void)
{
	unsigned char Pwmtemp;
	Pwmtemp = CCPR1L;
	CCPR1L = 0;
	Delay(500);
	Nop();
	ADCON0bits.DONE = 1;
	Nop();
	while(ADCON0bits.DONE);
	CCPR1L = Pwmtemp;
	adl = ADRESL;
	adh = ADRESH;
	return;	
}


void Delay(unsigned int count)
{
	while(count--);
	return;
}


#pragma code InterruptVectorHigh = 0x08
void
InterruptVectorHigh (void)
{
  _asm
    goto InterruptHandlerHigh
  _endasm
}

#pragma code
#pragma interrupt InterruptHandlerHigh

void InterruptHandlerHigh (void)
{
	INTCONbits.GIE = 0;
	
	if(PIR1bits.TMR2IF == 1)
	{
		PIR1bits.TMR2IF = 0;
		mTimer++;
		if(mTimer >= 100)
		{
			mTimer = 0;
			mTimer2++;
			
			if(mTimer2 >= 4)
			{
				Control.Pwm = 1;
				mTimer2 = 0;
				mTimer3++;
				if(mTimer3 >= 10)
				{
					mTimer3 = 0;
					Control.Display = 1;
				}
			}
		}
	}
	PIR1bits.ADIF = 0;
	INTCONbits.GIE = 1;
	return;
}


void WriteEEProm(unsigned char Data, unsigned char Address)
{
	EEADR = Address;
	EEDATA = Data;
	EECON1bits.EEPGD=0;
	EECON1bits.CFGS=0;
	EECON1bits.WREN=1;
	INTCONbits.GIE=0;					// This is the required sequence
	EECON2=0x55;
	EECON2=0xAA;
	EECON1bits.WR=1;
	Nop();
	INTCONbits.GIE=1;
	while(EECON1bits.WR);
	EECON1bits.WREN=0;
	return;
}


unsigned char ReadEEProm(unsigned char Adress)
{
	EEADR = Adress;
	EECON1bits.EEPGD = 0;
	EECON1bits.CFGS = 0;
	EECON1bits.RD = 1;
	Nop();
	return EEDATA;
}

void LoadData(void)
{
	Pointer = ReadEEProm(0);
	temp1 = ReadEEProm(1);
	temp2 = ReadEEProm(2);
	T1 = (((unsigned int)temp2 * 256) + (unsigned int)temp1);
	temp1 = ReadEEProm(3);
	temp2 = ReadEEProm(4);
	T2 = (((unsigned int)temp2 * 256) + (unsigned int)temp1);
	temp1 = ReadEEProm(5);
	temp2 = ReadEEProm(6);
	T3 = (((unsigned int)temp2 * 256) + (unsigned int)temp1);
	if(Pointer == 1)setpoint = T1;
	if(Pointer == 2)setpoint = T2;
	if(Pointer == 3)setpoint = T3;
}
