/*      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();

}