/*	mija 2009 - process

	SW pro ATmega8 mereni + regulace teploty
	Fosc = 8192000Hz externi krystal
	

	ver.: 0.0 - start	 
*/

#include <avr/io.h>
#include <stdio.h>
#include <math.h>

#include "process.h"
#include "key.h"
#include "lcd.h"
#include "clock.h"


uint8_t ProcesStart(char *buffer,uint8_t key,uint16_t temp)
{
	static uint8_t proces = SOLDER;
	static uint8_t displ = 1;
	static uint16_t LastTemp;
		
	HeatOff();
	if (key == TL1){
		displ = 1;
		return proces;
	}
	if ((key == TL2)){
		switch (proces)
		{
		case POSITIV: proces = DRY;
					break;	
		case DRY:	proces = SOLDER;
					break;
		case SOLDER:
		default: 	proces = POSITIV;
					break;
		}
		displ = 1;
	}
	if (displ){
		switch(proces)
		{
		case POSITIV:sprintf(buffer,"\fPOSITIV\n%3dC ch",temp);
					break;	
		case DRY: 	sprintf(buffer,"\fDRY\n%3dC ch",temp);
					break;
		case SOLDER:
		default: 	sprintf(buffer,"\fSOLDER\n%3dC ch",temp);
		}
		displ = 0;
	}
	else{
		if (temp !=LastTemp){
			sprintf(buffer,"\n%3d",temp);
			LastTemp=temp;
		}
	}
	return START;
}

/*uint8_t ProcesSolder(char *buffer,uint8_t key,uint16_t temp,Clockt_t *clock)
{
	enum{SOLDER_START,SOLDER_PREHEAT,SOLDER_SOLDER,SOLDER_COOL};
	static uint8_t stav=SOLDER_START;
	static uint8_t timer=PREHEATTIME;
	static uint8_t TimerFlag=0;
	static uint8_t PrevSec;

	if (key != NOKEY){
		stav = SOLDER_START;	
		return START;	
	}
	switch(stav)
	{
	case SOLDER_START:		
				timer = PREHEATTIME+1;
				TimerFlag = 0;
				stav = SOLDER_PREHEAT;
				ClockInit(0,0,0,clock);
				PrevSec = 0xff;
				sprintf(buffer,"\f");
				break;	
	case SOLDER_PREHEAT:
				if(temp >= PREHEATTEMPSTART) TimerFlag=1;
				ProcesHeat(PREHEATTEMP,temp);
				if (!timer){
					stav = SOLDER_SOLDER;
					timer = SOLDERTIME+1;
					TimerFlag = 0;
					PrevSec = 0xff;
				}
				sprintf(buffer,"\rpreheat\n%3dC %3ds",temp,timer-1);
				break;
	case SOLDER_SOLDER:
				if(temp >= SOLDERTEMP) TimerFlag=1;
				ProcesHeat(SOLDERTEMP,temp);
				if (!timer){
					stav = SOLDER_COOL;
					timer = COOLTIME+1;
					TimerFlag = 0;
					PrevSec = 0xff;
				}
				sprintf(buffer,"\rsolder \n%3dC %3ds",temp,timer-1);
				break;
	case SOLDER_COOL:
				HeatOff();
				TimerFlag=1;
				if (!timer){
					stav = SOLDER_START;
					PrevSec = 0xff;
					return START;
				}
				sprintf(buffer,"\rcool   \n%3dC %3ds",temp,timer-1);
				break; 
	default:	HeatOff();
				stav = SOLDER_START;
				return START;	
	}
	if ((PrevSec != clock->sec) && TimerFlag){
		PrevSec = clock->sec;
		timer --;
	}	
	return SOLDER;
}*/

uint8_t ProcesSolder(char *buffer,uint8_t key,uint16_t temp,Clockt_t *clock)
{
	enum{SOLDER_START,SOLDER_PREHEAT,SOLDER_SOLDER,SOLDER_COOL};
	static uint8_t stav=SOLDER_START;
	static uint8_t timer=PREHEATTIME;
	static uint8_t Timer2=0;
	static uint8_t TimerFlag2=0;
	static uint8_t TimerFlag=0;
	static uint8_t FlagSolder=0;
	static uint8_t PrevSec;
	static uint16_t LastTemp=0;

	if (key != NOKEY){
		stav = SOLDER_START;	
		return START;	
	}
	switch(stav)
	{
	case SOLDER_START:		
				timer = 0;
				TimerFlag = 0;
				Timer2 = 0;
				TimerFlag2 = 0;
				stav = SOLDER_PREHEAT;
				ClockInit(0,0,0,clock);
				PrevSec = 0xff;
				LastTemp = 0;
				sprintf(buffer,"\f");
				break;	
	case SOLDER_PREHEAT:
				if(temp >= PREHEATTEMPSTART) TimerFlag=1;
				if(temp >= PREHEATTEMP) TimerFlag2 = 1;
				if(temp >= PREHEATTEMPSTOP){
					stav = SOLDER_SOLDER;
					
					TimerFlag = 0;
					FlagSolder = 0;
					TimerFlag2 = 0;
					Timer2 = timer;
					timer=0;
					break;
				}
				if (TimerFlag2 && (Timer2 < PREHEATTIMEOFF)){
					if (LastTemp > temp) HeatOn();
					else {
						HeatOff();
						if ((clock->sec & 0x4) == 0x4) LastTemp = temp;		//4sec vzorkovani;
					}
					//LastTemp=temp;
				}
				else HeatOn();
				
				sprintf(buffer,"\rpreheat\n%3dC %3ds",temp,timer);
				break;
	case SOLDER_SOLDER:
				if(temp >= SOLDERTEMPSTART) TimerFlag=1;
				if(temp >= SOLDERTEMP) FlagSolder = 1;
				if (FlagSolder){
					HeatOff();
					if(temp <= SOLDERTEMPSTART){
						stav = SOLDER_COOL;
						timer=0x1;
						TimerFlag = 0;
						break;
					}
				}
				else HeatOn();
				if (TimerFlag) Timer2=timer;
				sprintf(buffer,"\rsolder \n%3dC %3ds",temp,Timer2);
				break;
	case SOLDER_COOL:
				HeatOff();
				TimerFlag=1;
				if (!timer){
					stav = SOLDER_START;
					//PrevSec = 0xff;
					return START;
				}
				sprintf(buffer,"\rcool   \n%3dC",temp);
				break; 
	default:	HeatOff();
				stav = SOLDER_START;
				return START;	
	}
	if ((PrevSec != clock->sec)){
		PrevSec = clock->sec;
		if (TimerFlag)timer ++;
		if (TimerFlag2) Timer2 ++;
	}

	return SOLDER;
}

uint8_t ProcesPositiv(char *buffer,uint8_t key,uint16_t temp,Clockt_t *clock)
{
	static uint8_t time = 0;
	static uint8_t PrevSec;
		
	if (!time){
		 time = POSITIVTIME+1;
		 ClockInit(0,0,0,clock);
		 PrevSec = 1;
	}
	ProcesHeat(POSITIVTEMP,temp);
	if (key == TL1) time +=5;
	if (key == TL2) {
			time = 0;
		return START;
	}
	if (PrevSec != clock->sec){
		PrevSec = clock->sec;
		if (PrevSec == 0) time --;
	}
	sprintf(buffer,"\n%3dC %3dm",temp,time);
	if (!time) return START;	
	return POSITIV;
}

uint8_t ProcesDry(char *buffer,uint8_t key,uint16_t temp,Clockt_t *clock)
{
	static uint8_t time;
	static uint8_t PrevSec;
		
	if (!time){
		 time = DRYTIME+1;
		 ClockInit(0,0,0,clock);
		 PrevSec = 1;
	}
	ProcesHeat(DRYTEMP,temp);
	if (key == TL1) time +=5;
	if (key == TL2) {
			time = 0;
		return START;
	}
	if (PrevSec != clock->sec){
		PrevSec = clock->sec;
		if (PrevSec == 0) time --;
	}
	sprintf(buffer,"\n%3dC %3dm",temp,time);
	if (!time) return START;	
	return DRY;
}

/*
uint8_t ProcesTest(char *buffer,uint8_t key,uint16_t temp,Clockt_t *clock)
{
	
	HeatOff();
	sprintf(buffer,"\r%2d:%02d:%02d\n%3dC    ",clock->hour,clock->min,clock->sec,temp);

	if (key == TL2) return START;
	return TEST;
}*/

void ProcesDispl(char *data)
{
	uint8_t a,b;

	for (a=0;a<MAXDISPLBUFFER;a++)
	{
		switch (*(data+a))
		{
		case 0: *data = 0;return;
		case '\n':	LCD_gotoxy(1,2);break;
      	case '\r':	LCD_gotoxy(1,1);break;
		case '\f':	LCD_gotoxy(1,1);
					for (b=0;b<8;b++) LCD_putc(0x20);
					LCD_gotoxy(1,2);
					for (b=0;b<8;b++) LCD_putc(0x20);
					LCD_gotoxy(1,1);
					break;
		default : 	LCD_putc(*(data+a));
    	}
	}
	*data = 0;
}

void ProcesTemp(uint16_t adc,uint16_t *temp)
{
	double Rpt;
	double Tpt;

	Rpt = 1.0*adc*2350.0/1024.0;
	
	#define A 3.90802e-3
	#define B -5.802e-7
	
	Tpt = (-A + sqrt(A*A - 4*B*(1.0 - Rpt/1000.0)))/2.0/B; 
	//Tpt = (-A + sqrt(A*A - 4*B*(1.0 - Rpt)))/2.0/B; 
	//Tpt = (Rpt/1000.0 - 1.0)/A;
	
	*temp = (int16_t)Tpt;
}

/*
void ProcesHeat(uint16_t temp,uint16_t ActualTemp)
{
	enum{HEAT_STABLE,HEAT_UP_1,HEAT_UP_2,HEAT_UP_3,HEAT_UP_4,HEAT_UP_5,HEAT_DOWN_1,HEAT_DOWN_2,HEAT_DOWN_3,HEAT_DOWN_4,HEAT_DOWN_5};
	static uint8_t stav = HEAT_STABLE;
	static uint8_t PrevTemp	= 0;
	static uint8_t TimeChange=0;

	if (ActualTemp < (temp)

	switch(stav)
	{
	case HEAT_STABLE:
				if (ActualTemp>temp) HeatOff();
				else HeatOn();
				break;
	case HEAT_UP_1:
				break;
	case HEAT_UP_2:
				break;
	case HEAT_UP_3:
				break;
	case HEAT_UP_4:
				break;
	case HEAT_UP_5:
				break;
	case HEAT_DOWN_1:
				break;
	case HEAT_DOWN_2:
				break;
	case HEAT_DOWN_3:
				break;
	case HEAT_DOWN_4:
				break;
	case HEAT_DOWN_5:
				break;
	}
	if (ActualTemp>temp) HeatOff();
	else HeatOn();
}
*/
/*
void ProcesHeat(uint16_t GequestTemp,uint16_t ActualTemp)
{

#define TERM_STOP 15             //teplotni rozdil do regulace - trouba topi
#define T1 20       //vzorkovani při naběhu teploty [s] 
#define T2 10       //vzorkovani při poklesu teploty [s]
#define T3  5       //vzorkovani při ustalene teplotě [s]   
#define T4  5       //doba topení [s] 
#define MAINCYKLSPEED	100	

	static uint8_t delta_s=0;
	static uint16_t T_LAST=0;
	static uint8_t	clock=MAINCYKLSPEED; 	//pocet opakovani teto fce za 1 sekundu



	if (!(-- clock)) {delta_s++;clock = MAINCYKLSPEED;}

	if( ActualTemp < (GequestTemp - TERM_STOP)){
        HeatOn();
        delta_s=0;
    	T_LAST=ActualTemp;
    }   
    else{
    	if (ActualTemp < GequestTemp){
        	if (ActualTemp == T_LAST){
            	if (delta_s < T1) HeatOff();
                else HeatOn();
                if (delta_s > (T1 + T4)) delta_s = 0;
           	}
            else{
            	if (T_LAST > ActualTemp) delta_s=(T1 - T2);
                else delta_s=0;
                T_LAST=ActualTemp;HeatOff();
            }   
     	}
        else{
        	HeatOff();T_LAST=ActualTemp;
            if (ActualTemp == GequestTemp) delta_s = (T1 - T3);
            else delta_s = 0;
       	}
	}   
}
*/
/*
void ProcesHeat(uint16_t RequestTemp,uint16_t ActualTemp)
{

#define TERM_STOP 15             //teplotni rozdil do regulace - trouba topi
#define T1 20       //vzorkovani při naběhu teploty [s] 
#define T2 10       //vzorkovani při poklesu teploty [s]
#define T3  5       //vzorkovani při ustalene teplotě [s]   
#define T4  5       //doba topení [s] 
#define	PERIOD	15	//[s]
#define MAINCYKLSPEED	100	

	static uint8_t delta_s=0;
	static uint16_t LastTemp=0;
	static uint8_t	clock=MAINCYKLSPEED; 	//pocet opakovani teto fce za 1 sekundu
	static uint8_t Pwm=0;
	static uint8_t DutyPwm = 0;
	static uint8_t FlagTemp = 1;
	static uint8_t FlagPwm = 0;



	if (!(-- clock)){
		delta_s++;
		clock = MAINCYKLSPEED;
		if ((++Pwm) > PERIOD){
			Pwm = 0;
			FlagPwm = 1;
		}
	}

	if( ActualTemp < (RequestTemp - TERM_STOP)){
        DutyPwm = PERIOD;
    	LastTemp = ActualTemp;
		FlagTemp=1;
	}
	else{
		if (FlagTemp){
			DutyPwm=0;
			FlagTemp = 0;
		}
		else
		if (FlagPwm)
		{
			FlagPwm=0;
			if (ActualTemp >= RequestTemp){
				if(LastTemp < ActualTemp ) { if (DutyPwm) DutyPwm --;}
			}		
			else{
				if (LastTemp >= ActualTemp) {if (DutyPwm<PERIOD)DutyPwm ++;}
			}
			LastTemp = ActualTemp;
		}
	}

	if(ActualTemp<RequestTemp){
		if (DutyPwm >= Pwm) HeatOn();
		else HeatOff();
	}
	else HeatOff();

}*/

void ProcesHeat(uint16_t RequestTemp,uint16_t ActualTemp)
{

#define TERM_STOP 15             //teplotni rozdil do regulace - trouba topi

#define	PERIOD	15	//[s]
#define MAINCYKLSPEED	100	

	static uint8_t delta_s=0;
	static uint16_t LastTemp=0;
	static uint8_t	clock=MAINCYKLSPEED; 	//pocet opakovani teto fce za 1 sekundu
	static uint8_t Pwm=0;
	static uint8_t DutyPwm = 0;
	static uint8_t FlagTemp = 1;
	static uint8_t FlagPwm = 0;



	if (!(-- clock)){
		clock = MAINCYKLSPEED;
		if ((++Pwm) > PERIOD){
			Pwm = 0;
			FlagPwm = 1;
		}
	}

	if( ActualTemp < (RequestTemp - TERM_STOP)){
        DutyPwm = PERIOD;
    	LastTemp = ActualTemp;
		FlagTemp=1;
	}
	else{
		if (FlagTemp){
			DutyPwm=0;
			FlagTemp = 0;
		}
		else
		if (FlagPwm)
		{
			FlagPwm=0;
			if (ActualTemp >= RequestTemp){
				if (ActualTemp != RequestTemp)
				if(LastTemp < ActualTemp ){
					//if ((ActualTemp-LastTemp) > 1)
						if (DutyPwm) DutyPwm --;
				}
			}		
			else{
				if (LastTemp >= ActualTemp){
					//if ((ActulaTemp - LastTemp)>1)
						if (DutyPwm<PERIOD)DutyPwm ++;
				}
				if(LastTemp < ActualTemp ){
					if ((ActualTemp-LastTemp) > 5)
						if (DutyPwm) DutyPwm --;
				}
			}
			LastTemp = ActualTemp;
		}
	}

	if(ActualTemp < RequestTemp)
	{
		if (DutyPwm == PERIOD) HeatOn();
		else{
			if (DutyPwm > Pwm) HeatOn();
			else HeatOff();
		}
		
	}
	else HeatOff();

}
