#include <stdio.h>
#include <c:\Keil\C51\INC\AtmelWM\89c51rd2.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define LCD_RW	P0_6
#define LCD_RS	P0_5
#define LCD_E	P0_7


/*********************** STRUKTURY *****************************************************/

struct tag_temperature{ 	float Value;					// teplota jako float cislo
							unsigned char Temp_str[7];};	// teplota jako string

struct tag_channel{			unsigned int Value;				// ciselna hodnota prevodu z AD
							unsigned char  AD_str[13];
							/*unsigned int buffer;*/};		    // prevod AD


/********************************************************************************/
int data counter_2 = 0;
int data counter = 0;
char data transmit_data[13];			//vysilani	
unsigned char data receive_char[3];		//prijmuty byte
struct tag_channel Channel_0,Channel_1;
struct tag_temperature Temp_0,Temp_1;
sbit CS = 0x91;	//P1.1
bit priznak;
bit sample_flag;
bit r=0;
char data VAL_str[6];
char data T[3];

int data VALUE = 0;
unsigned int data buffer0, buffer1;




void clock()
{
	unsigned int i = 0;
	P0_7 = 1;
	while(i<100){i++;}i = 0;
	P0_7 = 0;
	while(i<100){i++;}i = 0;
	
}
bit check_BF()
{
	P0_5 = 0;//RS 0
	P0_6 = 1;//rw 1
	clock();
	if (P2_7 == 1)
	return(1);
	else
	{
		P0_6 = 0;
		return(0);	
	}
}
void LCD_clr() large
{
P2 = 0x01;
clock();	// return home
while (check_BF());
}
void LCD_position(unsigned char addr) large
{
	
	if ((addr >= 1) && (addr <= 20)) (P2 = (0x80 + addr - 1));
	else if((addr >= 21) && (addr <= 40)) (P2 = (0xC0 + addr - 21));
	else if((addr >= 41) && (addr <= 60)) (P2 = (0x94 + addr - 41));
	else (P2 = (0xD4 + addr - 61));
	LCD_RW = 0;
	LCD_RS = 0;
	clock();
	
}
/*****************LCD init ******************************/
void LCD_init() large
{
P2 = 0x38;	//function set - 8bit bus,2 lines, font
clock();
while (check_BF());
P2 = 0x0C;	//display ON, no cursor , no blink						  
clock();
while (check_BF());
P2 = 0x01;
clock();	// return home
while (check_BF());
P2 = 0x06;	//mode set - increment, no shift
clock();
}


void LCD_send_text(char text[20])
{
int i=0;
	while(text[i] != '\0')
	{
		P0_5 = 1;
		P2 = text[i] ;  // zapis znaku
		i++;
		clock();
		
	}
	i=0;	
}


void LCD(float data PTT,float data KK) 
{
static float data PT,K;
T[0]= 0xdf;
T[1]= 'C';
T[2]= '\0';
if (KK != K) 
{
	K = KK;
	LCD_position(4);
	LCD_send_text(Temp_0.Temp_str);
	LCD_send_text(T);

}
if (PTT != PT) 
{
	PT = PTT;
	LCD_position(14);
	LCD_send_text(Temp_1.Temp_str);
	LCD_send_text(T);
	
}
}
/****************** SPI init ******************************/

void spi_init()
{  	//SPR2 SPEN SSDIS MSTR CPOL CPHA  SPR1 SPR0
	//	1	1	  1		1	0	  0		1   0	
	SPCON = 0xF2;
	
}

/****************** UART init ******************************/
void uart_init()
{
	SCON = 0x50;			//mode 1, REN=1
	TMOD = TMOD | 0x20;		//T1 in mode 2
	TH1 = 0xFD;				//BdR 9600
	TL1 = 0xFD;				//BdR 9600
	ES = 1;					//enable serial interrupt
	EA = 1;					//enable global interrupt
	TR1 = 1;				//run T1	
}
/****************** PWM init ********************************/
void pwm_init()
{
	CMOD &= 0xFD;			// CPS0 = 0, nastaveni PCA pro clockovani timerem0
	CMOD |= 0x04;  			// CPS1 = 1, nastaveni PCA pro clockovani timerem0
	CCAPM1 |= 0x02;			// nastaveni PWM na modulu 1
	CCAPM1 |= 0x40;			// povoleni komparatoru pro  PCA modul 1
	CCON |= 0x40;			// start PCA
	TMOD |= 0x01;			// T0 mode 1
	ET0 = 1;
	TH0 = 0xDB;
	TL0 = 0xA2;
	TR0 = 1; 
}  										 
/****************** bin to hex ******************************/
char bin_to_hex(unsigned char in)
{
	const char xdata table[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	return table[in & 0x0f];
}

/****************** SPI rw ******************************/
unsigned char spi_rw(unsigned char in)		
{
	SPDAT = in;
	while (!(SPSTA & 0x80));
	return SPDAT;
}

/****************** AD measure ******************************/
unsigned int ad_measure(unsigned char init)	large		// vstup je nastaveni AD
{
	unsigned int data temp;
	P1_1 = 0;
	spi_rw(0x01);
	temp = spi_rw(init);
	temp &= 0x0F;
	temp <<= 8;
	temp |= spi_rw(0x00);
	P1_1 = 1;
	return temp;
}

/****************** Uart putchar ******************************/
void uart_putch(char ch)
{
	SBUF = ch;
	while (TI == 0);
	TI = 0;
}

/****************** Uart send ******************************/
//			  cislo kanalu	ukazatel na Temp.str	
void uart_send(unsigned int value,char channel,char *pPole) large
{
		uart_putch('C');
		uart_putch('H');
		uart_putch(channel + 0x30);
		uart_putch('=');
		
		uart_putch('0');
		uart_putch('x');
		uart_putch(bin_to_hex((value >> 8) & 0x0f));
		uart_putch(bin_to_hex((value >> 4) & 0x0f));
		uart_putch(bin_to_hex(value & 0x0f));
		uart_putch('\t');
		uart_putch('*');
		uart_putch('T');
		uart_putch('=');
		
			while (*pPole != '\0')
			{
				uart_putch(*pPole);
				pPole ++;
			}
		
		uart_putch(0x0D);
}
/****************** Channel Value ******************************/
void channel_value_send()large
{
	
	switch (receive_char[0])
	{
		case '0':	(uart_send(Channel_0.Value,0,Temp_0.Temp_str));break;
		case '1':	(uart_send(Channel_1.Value,1,Temp_1.Temp_str));break;	 
		case 'A':	CCAP1H = 0x00; break;
		case 'B':	CCAP1H = 0x40;break;
		case 'C': 	CCAP1H = 0x80;break;
		case 'D': 	CCAP1H = 0xC0;break;
		case 'E': 	CCAP1H = 0xFF;break;
		default :	{
					uart_putch('*');
					uart_putch('s');
					uart_putch('e');
					uart_putch('t');
					uart_putch('-');
					uart_putch('C');
					uart_putch('H');
					uart_putch(0x0D);
					break;
					}
	}
}
void xxx(float a,unsigned char *b) large
{
	sprintf(b,"%01.1f",a);
} 
/****************** Temperature ch1 (termistor PT100)******************************/

float temperature_ch1(unsigned int cislo)
{
return((0.1095 * cislo) - 5.4861);	
}  
/****************** Temperature ch0 (termoclanek K) ******************************/
/* NUTNO ODKOMENTOVAT PRI POZADAVKU MERENI NA OBOU KANALECH*/
/*
float temperature_ch0(unsigned int cislo)large
{
		
return(((cislo * 0.0007324)* 0.0985) + 0.7417);
} 
  */
//////////////////////buttons /////////////////////////
void UP()large
{
if (VALUE >=0 && VALUE <= 300)
VALUE++;
else
VALUE = 0;
xxx(VALUE,VAL_str);
LCD_position(46);
LCD_send_text(VAL_str);
LCD_send_text(T);
	
}
void DOWN()large
{
if (VALUE >=0 && VALUE <= 300)
VALUE--;
else
VALUE = 300;
xxx(VALUE,VAL_str);
LCD_position(46);
LCD_send_text(VAL_str);
LCD_send_text(T);
	
}
void Enter()
{
r = !r;
LCD_position(55);
if (r)
{
LCD_send_text("RUN!");
}
else
LCD_send_text("STOP");
}


void button() large
{
	unsigned int k = 0;

	if (P0_0 == 1)
	{
		UP();
		while(k<1000){k++;}
	}
	else if (P0_2 == 1)
	{
		Enter();
		while(k<5000){k++;}
	}
	else if (P0_1 == 1)
	{
		DOWN();
		while(k<1000){k++;}
	}
}

/******************REGUL**************************************/
void reg(int zadana)large
{
const float data Ti = 6.2253e-004;
//const float data Td/Tvz = 218.2189;
//const float data k = 3;

static float data e;
static float data e_1;
static float data y=0;
static float data x;

 
//Temp_0.Value = temperature_ch0(Channel_0.Value);  // NUTNO ODKOMENTOVAT PRI MERENI NA OBOU KANALECH
Temp_1.Value = temperature_ch1(Channel_1.Value);
xxx(Temp_0.Value,Temp_0.Temp_str);
xxx(Temp_1.Value,Temp_1.Temp_str);

if (r)
{
e_1 = e;
e = (zadana - Temp_1.Value)*3;
y = e + (e*(Ti+x)*((e_1)/(1-e_1))) + ((e*3) * (1-e_1)/(1-0.9863*e_1));
if (y > 255)
{
CCAP1H = 255;
}
else if (y<0)
{
CCAP1H = 0;
}
else
CCAP1H = y;

x = (CCAP1H - y)*0.0008;

}
else
{ 
CCAP1H = 0;		  
}
}	  


/*************************************************************/
/*************************************************************/
int main (void)
{
	
   	EA = 0;
	uart_init();
	spi_init(); 
	pwm_init();
	LCD_init();
	CCAP1H = 0x00;
	P1_3 = 0;
	LCD_send_text("T0:");
	LCD_position(11);
	LCD_send_text("T1:");
	LCD_position(41);
	LCD_send_text("SET:");
	xxx(VALUE,VAL_str);
	LCD_position(46);
	LCD_send_text(VAL_str);
	LCD_send_text(T);
	
	while(1)
	{
		LCD(Temp_1.Value,Temp_0.Value);
		button();
		if (counter == 16)
		{
			Channel_0.Value = buffer0 / 16;
			Channel_1.Value = (buffer1 / 16);
			buffer0 = 0;
			buffer1 = 0;
			P1_3 = !P1_3;
			reg(VALUE);

			counter = 0;	
		}
		
		if (priznak == 1)
		{
			channel_value_send();
			receive_char[0] = 0x00;
			priznak = 0;
		}		
		
	}
}


/********************interrupts ******************************/

void T_PCA(void) large interrupt 1
{
	if (counter_2 == 16)
	{
		buffer0 += ad_measure(0xA0);				// meas channel 0
		buffer1 += ad_measure(0xE0);				// meas channel 1
		counter_2 = 0;
		counter++;
	}
	else
	counter_2++;
	TH0 = 0xDB;
	TL0 = 0xA2;
	TF0 = 0;
}
void uart_read(void)large interrupt 4
{	
	if (RI == 1)
	{	
		receive_char[0] = SBUF;
		RI = 0;
		priznak = 1;
		
	}

	else;

}

 