#include <stdio.h>
#include <string.h>
#include <ADuCM360.h>
#include <math.h>

//--------------------------konstanty a hodnoty RTD, pt100 a termoclanek-----------------------------------
float fVRTD = 0.0 ;                       // napeti na RTD 
float fVPTV = 0.0 ;                       // napeti na vnejsi PT100
float fRrtd = 0.0;                        // odpor RTD
float fRPTV = 0.0;                        // odpor na PT100 vnejsi
float fTRTD = 0.0;                        // teplota na RTD
float fTPTV = 0.0;                        // teplota na vnejsi pt100
float fIexc0 = 0.0002;                    // hodnota excitacniho proudu 
float fVTC =0.0;                          // napeti termoclanku
float fTTC =0.0;                          // teplota termoclanku
double a1 =  2.5084e-2;                   // konstanty pro termoclanek
double a2 =  7.8601e-8;
double a3 = -2.5031e-10;
double a4 =  8.3153e-14;
double a5 = -1.2280e-17;
float A = 3.9083e-3;
float B = -5.775e-7;
float fVFW = 0.0;                         // napeti volnich konci
float fSUMV = 0.0;                        // suma napeti volnich konci a termoclanku
signed long int fVNeg;                    // hodnota pro zaporni prevod

//--------------------------------------konstanty a hodnoty volnich konci---------------------------------------
#define FW_T_MIN_P (0)  									// minimalni kladna teplota v stC 
#define FW_T_MAX_P (300)									// maximalni kladna teplota v stC
#define FW_V_MIN_P (0)  									// napeti v mV pri 0 stC
#define FW_V_MAX_P (12.209) 							// napeti v mV pro 300 stC
#define FW_SEG_P (60) 		  							// pocet hodnot v tabulce
#define FW_T_SEG_P (5)		  							// (FW_T_MAX-FW_T_MIN)/FW_N_SEG = teplota v stC na kazdy segment
const float C_FW_Positive[FW_SEG_P+1] = {0.0, 0.198, 0.397, 0.597, 0.798, 1.000, 1.203, 1.407, 1.612, 1.817,
																				 2.023, 2.230, 2.436, 2.644, 2.851, 3.059, 3.267, 3.474, 3.682, 3.889,	
																				 4.096, 4.303, 4.509, 4.715, 4.715, 5.124, 5.328, 5.532, 5.735, 5.937,
																				 6.138, 6.339, 6.540, 6.741, 6.941, 7.140, 7.340, 7.540, 7.739, 7.939,
																				 8.138, 8.338, 8.539, 8.739, 8.940, 9.141, 9.343, 9.545, 9.747, 9.950,
																				 10.153, 10.357, 10.561,	10.766, 10.971, 11.176, 11.382, 11.588, 11.795,
																				 12.001, 12.209};
#define FW_T_MIN_N (0)  									// minimalni zaporna telplota v stC 
#define FW_T_MAX_N (-40)	  							// maximalni zaporna telplota v stC 
#define FW_V_MIN_N (0)  									// napeti v mV pro 0 stC 
#define FW_V_MAX_N (-1.527)								// napeti v mV pro -40 stC 
#define FW_SEG_N (8) 		    							// pocet hodnot v tabulce
#define FW_T_SEG_N (-5) 									// (FW_T_MAX-FW_T_MIN)/FW_N_SEG = teplota v stC na kazdy segment
const float C_FW_Negative[FW_SEG_N+1] = {0.0,		-0.197,	-0.392,	-0.586,	-0.778,
																				-0.968,	-1.156,	-1.343,	-1.527};
																					//je tam N_SEG+1 kvuli 0 navic v kazde rade										

void delay(long int length);											
void Send_Uart (char x);          				// posilani 1 symbolu
void Send (char Buff[]);									// posilani cele hodnoty							
void UARTINIT(void);						  				// iniciace uartu
void IEXCINIT(void);              				// iniciace proudu cidlem
void CLOCK (void);                				// nastaveni casovace
float CalculateRTDTemp(float r);  				// funkce vypoctu teploty na RTD
float CalculateFreeWireVolt(float r); 		// funkce vypoctu napeti na volnich konci termoclanku

int main (void) {
	pADI_GP1->GPOEN  =  0x8;                // GPIO1.3 is output   
	pADI_GP1->GPSET  =  0x8;                // switch LED off       
	CLOCK();                        
	UARTINIT();                         
	IEXCINIT();
	
while (1)
{
//---------------------------------------------napeti na RTD mezi AIN0 a AIN1------------------------------------------

		 pADI_ADC1->CON = 0x8C001;						// zapnuti periferie 
		 pADI_ADC1->MDE = 0x51;           		// g=32 nekonecny prevod 
		 pADI_ADC1->FLT = 0x8D7C;         		// 3.53Hz sampling rate, chop off
		 delay(100);
	
		 int d = 0;
		 while (d==0) {
				d = pADI_ADC1->STA&1;
	   }

		 fVRTD = pADI_ADC1->DAT;         			// cteni hodnoty napeti
		 fVRTD = fVRTD*1.2  / 268435456; 			// prepocet napeti 

//----------------------------------------------spocitame teplotu na rtd------------------------------------------------

     fRrtd = fVRTD/fIexc0;                     			// odpor na RTD 
		 fRrtd = fRrtd - (0.013*fRrtd + 0.046);         // rovnice chyby                         
		 fTRTD = (-A+sqrt(A*A-4*B*(1-fRrtd/100)))/2/B;  // RTD teplota

//--------------------------------------------------napeti na termoclanku mezi AIN2 to AIN3-----------------------------

		 pADI_ADC1->CON = 0x00001;       			// adc1 mezi ain0 a ain1 off
		 pADI_ADC0->CON = 0x8C043;       			// ain2 a ain3, zapnuti
		 pADI_ADC0->FLT = 0x8D7C; 			 			// 3.53Hz sampling rate, chop off
		 pADI_ADC0->MDE = 0x71;          			// g=128 nekonecny prevod          	
	
		 fVFW = CalculateFreeWireVolt(fTRTD); // pomoci zavislosti napeti volnich konci na jejich teplote, teplota = teplote RTD
		 
		 d = 0;
		 while (d==0) {
				d = pADI_ADC0->STA&1;
	   }
		
		 fVNeg = pADI_ADC0->DAT;               // nactu hodnotu
		 fVTC = fVNeg;                         // zapisu do jine promenne pro zachovani "-"
		 fVTC = fVTC*1.2 / 268435456;          // prepocet napeti	 
		 fSUMV = fVFW + fVTC;           		   // suma napeti 
		 fSUMV = fSUMV*1000000;		 		  		   // prevod na uV
		 
		 fTTC = a1*fSUMV+a2*fSUMV*fSUMV+a3*fSUMV*fSUMV*fSUMV+a4*fSUMV*fSUMV*fSUMV*fSUMV+a5*fSUMV*fSUMV*fSUMV*fSUMV*fSUMV; 

//--------------------------------teplota vnejsiho PT100-------------------------------------
		
		 pADI_ADC0->CON = 0xC043;        			 // ain2 a ain3 adc off
		 pADI_ADC1->CON = 0x8C085;				 		 // zapnuti periferie
		 pADI_ADC1->MDE = 0x51;           		 // g=32 nekonecny prevod
		 pADI_ADC1->FLT = 0x8D7C;         		 // 3.53Hz sampling rate, chop off

	   d = 0;
		 while (d==0) {
				d = pADI_ADC1->STA&1;
	   }

		 fVPTV = pADI_ADC1->DAT;         			 // cteni hodnoty napeti
		 fVPTV = fVPTV*1.2 / 268435456; 			 // vypocet napeti	
		 fRPTV = fVPTV/fIexc0;                 // PT100 resistance
		 fRPTV = fRPTV - (0.013*fRPTV + 0.737);// rovnice chyby
		 fTPTV = (-A+sqrt(A*A-4*B*(1-fRPTV/100)))/2/B;//prepocet na teplotu
		 
//-------------------------------------vypinani vseho-------------------------------------------		 
		 
		 //ADC0 je veply
		 pADI_ADC1->CON = 0x00001;       			 // adc1 mezi ain0 a ain1 off		 
		 pADI_ANA->REFCTRL = 0x1;				 			 // vypinam proud Iexc
		 
//-----------------------------------posilani vysledku------------------------------------------		 
		 
		 char buffer[8] ; 
		 sprintf(buffer, "%f", fTRTD);         // posilam teplotu rtd
  	 Send(buffer);	  
		 sprintf(buffer, "%f", fTTC);          // posilam teplotu termoclanku
  	 Send(buffer);	
		 sprintf(buffer, "%f", fTPTV);         // posilam teplotu pt100 vnejsi
  	 Send(buffer);	 
		 
		 char buffer1[8] ;
		 buffer1[0] = '\n';
  	 Send(buffer1);	 
		 
		 pADI_GP1->GPCLR = 0x8;            		 // Turn on LED        
		 delay(100000);
		 pADI_GP1->GPSET = 0x8;            		 // Turn off LED         	
     
		 SCB->SCR = 0x04; 										 // sleepdeep mode
		 pADI_PWRCTL->PWRKEY = 0x4859; 			   // key1
		 pADI_PWRCTL->PWRKEY = 0xF27B; 			   // key2
		 pADI_PWRCTL->PWRMOD = 0x4; 					 // vyber sleep modu	 
	 	 __WFI();}
}
void UARTINIT(void){
	pADI_UART->COMCON= 0x0;    							 // enable uart
	pADI_GP0->GPCON |= 0x3C;   							 // Configure P0.1/P0.2 for UART 
  pADI_UART->COMLCR= 0x3;	   							 // no parity, 1 stop bit, 8 data bits
	pADI_UART->COMDIV= 0x2;    							 // comdiv=2
	pADI_UART->COMFBR= 0x915C; 						   // baud rate 115200 divm=2 divn=384 
}
void IEXCINIT(void){	
	pADI_ANA->REFCTRL = 0x0;							   // enable reference
	pADI_ANA->IEXCDAT = 0xE;							   // Set output for 0,2mA - 0b00001110
	pADI_ANA->IEXCCON = 0x74;								 // Setup Iexc for AIN6  -0b01110000 a ain4 01000100
}
float CalculateFreeWireVolt(float r) 
{
	float fresult = 0;
	signed int j = 0;
	if (r >= 0)
	{
  		j=(r - FW_T_MIN_P) / FW_T_SEG_P;		 // vyber koufecientu
  		if (j>FW_SEG_P-1)     							 // pokud je koef overrange
    		j=FW_SEG_P-1;            					 // tak vyberu maximalni
		
		  // vyberu nejblizsi hodnoty
      fresult = C_FW_Positive[j] + (r - (FW_T_MIN_P+FW_T_SEG_P*j) )*(C_FW_Positive[j+1]-C_FW_Positive[j]) / FW_T_SEG_P;		 
	}
	else if (r < 0)
	{
		j=(j - FW_T_MIN_N) / FW_T_SEG_N;			 // vyber koufecientu
		if (j>FW_SEG_N-1)    							     // pokud je koef overrange
    		j=FW_SEG_N-1;         						 // tak vyberu maximalni

		fresult = C_FW_Negative[j] + (r - (FW_T_MIN_N+FW_T_SEG_N*j) )*
			(C_FW_Negative[j+1]-C_FW_Negative[j]) / FW_T_SEG_N;
	}
	return fresult/1000.0;
}
void Send_Uart (char x){
		while (!(pADI_UART->COMLSR == 0))
    pADI_UART->COMTX=x;
}
void Send (char Buff[]) {
	int cnt=0; 
	int cnt1=0; 
	int i=0;

	Send_Uart(0x02);                           // zacatek zpravy
	delay(700);                         	
	
	cnt1=strlen(Buff);												 // cnt1=delka Buff
			while (cnt<cnt1) {										 // posilam celou hodnotu
				if (1) {
				Send_Uart(Buff[cnt]);
				i=0;
				delay(500); }
				cnt++;
			}
		delay(700);                       
	Send_Uart(0x0d);			                     // konec zpravy
}
void delay(long int length){
	while (length>0) 
	length--;
}
void CLOCK (void){
  pADI_CLKCTL->CLKCON0   = 0x0;              // 16MHz UCLK  
  pADI_CLKCTL->CLKSYSDIV = 0;                // 16MHz system clock 
  pADI_CLKCTL->CLKCON1   = 0x0;              // PWM = 16MHz, UART = 16MHz, SPI1 = 16MHz, SPI0=16MHz 
  pADI_CLKCTL->CLKDIS    = 0x0;              // Enable clock
 
	pADI_WDT->T3CON = 0x0; 									   // vypnu watchdog timer
  pADI_WDT->T3LD = 0x100;  									 // 0x1000 = 32 sek1 0x100 - 2sek 
  pADI_WDT->T3CON = 0x69;  									 // reset
}
