/*

    v1.0
	
	PSD


*/

#include<ADuC7020.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

void My_IRQ_Handler(void);

//short i = 0;
unsigned char Byte_addr = 0;
int first = 1;
int i2c_cnt = 0;

#define BIGDAT_SZ 256
unsigned short BigDat[BIGDAT_SZ];
char text[512];

unsigned short Vout[4];

//unsigned short Vlearn;

double Vin[5];

unsigned short remote_trigg,wf_len; 

//unsigned short start, stop,start_gnd,stop_gnd,start2,stop2,Vset, step_max,N;

unsigned char busy,channel;

unsigned int trigg_cnt,v_cnt,wf_cnt;


//char format	= 0;


unsigned char* pbuff;

unsigned char* plist[256];



void delay (int length)
{
	while (length >=0)
    	length--;
}


// conversion of the read value into it corresponding 12bits integer
int ADCtoDAT(unsigned long ADC)
{
	return (ADC&0xFFF0000)>>16;
}

unsigned long DATtoADC(int DAT)
{
	unsigned long ADC;
	ADC=DAT;
	return ADC<<16;
}

unsigned long DATtoDAC(unsigned short DAT)
{
	unsigned int ADC;
	ADC=DAT;
	return ADC<<16;
}


int Read_Digital(int n)
{	
    return ((GP0DAT&0x000000FF)>>n)&0x1;
}

void Write_Digital(int n, int state)
{	
    if(state==1)
	  GP2DAT=(0x00000001<<(n+16))|GP2DAT;
	else 
		GP2DAT=~((0x00000001<<(n+16))|(~GP2DAT));
}


void ADCpoweron(int time)
{
	ADCCON = 0x620;	 			// power-on the ADC
	while (time >=0)	  		// wait for ADC to be fully powered on
    time--;
}




void get_DACs(void)
{
	Vout[0]=DAC0DAT>>16;
	Vout[1]=DAC1DAT>>16;
	Vout[2]=DAC2DAT>>16;
	Vout[3]=DAC3DAT>>16;	
}

void set_DACs(void)
{
	DAC0DAT=DATtoDAC(Vout[0]);
	DAC1DAT=DATtoDAC(Vout[1]);
	DAC2DAT=DATtoDAC(Vout[2]);
	DAC3DAT=DATtoDAC(Vout[3]);
}

void lock_StabPulse_i2c(void)
{
	// define variables
//	unsigned int cnt_N;
	double sum;//,sum_gnd;
//	unsigned short Vout2;
	//double Vin,Vin_gnd;
	//int Vmean;
//	int step = 100;
	short armed; // this is used to detect the trigger : 
				 // when the trigger input is low armed is set to 1
				 // when a measurement start it is set to 0
//	short valid_data;
	int k,i;
	unsigned short Data[256];
	//unsigned int tmp_dat[256];


	POWKEY1 = 0x01;
	POWCON = 0x00;		   				// 41.78MHz
	POWKEY2 = 0xF4;
	 

	//GP1CON = 0x00000000;    // IO initialization
	//GP1DAT = 0xFF000000;	// set P1.n as digital output
	
	GP0CON = 0x00000000;	// IO initialization
	//GP0DAT = 0x00000000;	// set P0.n as digital input



	// ADC&DAC setting
	ADCpoweron(20000); // power on ADC
	REFCON = 0x01;	   // internal 2.5V reference
	DAC0CON = 0x12;	   // AGND-ARef range 0x12 2.5V
	DAC1CON = 0x12;	   // AGND-ARef range 0x12 2.5V
	DAC2CON = 0x12;	   // AGND-ARef range 0x12 2.5V
	DAC3CON = 0x12;	   // AGND-ARef range 0x12 2.5V
	ADCCP = 0x03;	   // conversion on ADC0
	ADCCON = 0x3E4;    // continuous conversion

	// IO setting
    GP2CON = 0x00000000;    // IO initialization
	GP2DAT = 0xFF000000;	// set P2.n as digital output
	GP0CON = 0x00000000;	// IO initialization
	GP0DAT = 0x00000000;	// set P0.n as digital input
	

	// locking parameters initialization
//	cnt = 0;      // 
//	N = 1;       // number of measume,ts for averaging
//	Vin = 0;      // initialize the voltage of first step
//	Vin_gnd = 0;
//	Vmean = 2000;
//	start = 20;	
//	stop = 30;
//	start_gnd = 0;
//	stop_gnd = 10;
	wf_len = 200;
//	Vset = 200;
//	Vlearn = 2000;
//	step = 50;
//	step_max = 100;
//	Gain = 1;


	// I2C on P1.0 and P1.1
 	GP1CON = 0x22;

	IRQ = My_IRQ_Handler;
	IRQEN = 0x200;					// I2C0 Slave Interupt
	
	I2C0CFG = 0x04001;
	// Slave ID		  		
	I2C0ID0 = (0x50 + (((GP0DAT&0x000000FF)>>5)&0x1)+(((GP0DAT&0x000000FF)>>7)&0x1)*2)<<1;
	I2C0STX = 0x00;
	I2C0STX = 0x00;

	// assignation of the different pointers for the I2C exchange of data
	for (k=0;k<16;k++){
		plist[k] = (unsigned char*)(BigDat+k*16);
		plist[k+50] = (unsigned char*)(text+k*32);
	}
	
	for(i=0;i<BIGDAT_SZ;i++)
		BigDat[i]=0;

	sprintf(text,"pulse stabilization v1.2 => %s\ncompiled: %s\nbecause we can!",__func__,__DATE__);
	
	for (k=0;k<4;k++){
		plist[100+k] = (unsigned char*)(Vout+k);
	}
	// 104	to execute the function get_DACs
	// 105	to execute the function set_DACs
	
	//plist[110] = (unsigned char*)&(Vin[0]);
	//plist[111] = (unsigned char*)&(Vin[1]);
	//plist[112] = (unsigned char*)&(Vin[2]);
	//plist[113] = (unsigned char*)&(Vin[3]);
	//plist[114] = (unsigned char*)&(Vin[4]);
	for (k=0;k<5;k++){
		plist[110+k] = (unsigned char*)(Vin+k);
	}
	
	//plist[114] = (unsigned char*)&v_cnt;
	plist[115] = (unsigned char*)&remote_trigg;	

	plist[120] = (unsigned char*)&I2C0ID0;
	plist[121] = (unsigned char*)&channel;
//	plist[122] = (unsigned char*)&transf;
	plist[123] = (unsigned char*)&wf_len;
	plist[124] = (unsigned char*)&trigg_cnt;

//	plist[125] = (unsigned char*)&Vset;
//	plist[126] = (unsigned char*)&N;
//	plist[127] = (unsigned char*)&start;
//	plist[128] = (unsigned char*)&stop;
//	plist[129] = (unsigned char*)&start2;
//	plist[130] = (unsigned char*)&stop2;
//	plist[131] = (unsigned char*)&start_gnd;
//	plist[132] = (unsigned char*)&stop_gnd;
//	plist[133] = (unsigned char*)&enab_gnd;
//	plist[134] = (unsigned char*)&Gain;
//	plist[135] = (unsigned char*)&step_max;
	
		
	
		
//	DAC0DAT = DATtoADC(10);
//	DAC1DAT = DATtoADC(20);
//	DAC2DAT = DATtoADC(2000);
//	DAC3DAT = DATtoADC(40);
	
//	Vset=0;

//	Vout[3] = 111;
//	set_DACs();

//	transf = 0;
//	trigg_cnt = 0;
//	wf_cnt = 0;
//	v_cnt = 0;
//	cnt_N = 0;
//	enab_gnd = 0;
	remote_trigg = 0;
	channel = 0;
//	valid_data=0;


	// main loop for the locking
	while(1){
	
		// trigg in is on p0.3 => we check that it is low first (rising edge detection)
		if((((GP0DAT&0x000000FF)>>3)&0x1)==0){
			armed = 1;
		}		

		// now p0.3 is high => this is our rising edge
		if(((((GP0DAT&0x000000FF)>>3)&0x1)==1 && armed==1) || remote_trigg){
			
			armed = 0;
			//busy = 0;	
			//*** aquisition of the waveform  ***
			
		 
			for(i=1;i<5;i++){
				ADCCP = i;			
			
				for(k=0;k<wf_len;k++){
					while(!ADCSTA){}	// wait for the end of ADC conversion
					Data[k]= (unsigned short)(ADCDAT >> 16); // read voltage from ADC0
				}
			
				
				//if(busy==0){ // supposed to guaranty that no i2c transfer has been performed during the wf acquisition
					//*** copy for the i2c ***			
				
					if(i==channel){
						memcpy(BigDat,Data,256*sizeof(short));
					}
						
					sum = 0; // initialization	of the measurement
					for(k=0;k<wf_len;k++){
						sum += Data[k];
					//cnt++;
					}
				
					Vin[i] = sum/wf_len;	// calculate average value
//					valid_data = 1;
				
				//}
//				else busy = 0;
			} 
			remote_trigg=0;
			
		}
		
	}
}




int main(void)
{ 
	
	lock_StabPulse_i2c();

	return 0;
}





/*************************************************/
/*************************************************/
/************	IRQ Service Routine  *************/
/*************************************************/
/*************************************************/



void My_IRQ_Handler()
{
	int status = I2C0SSTA;
	busy = 1;
	
	// Slave Recieve
	if ((status & 0x08)==0x08)   // Slave Recieve IRQ
	{			
			if(first==1){
				first=0;
				Byte_addr=I2C0SRX;
				I2C0FSTA|= 1 << 8;

				i2c_cnt = 0;
//				if(Byte_addr==122)
//					transf = 1;
				if(Byte_addr==104)
					get_DACs();
				if(Byte_addr==105)
					set_DACs();

				Write_Digital(2,0);
				pbuff = plist[Byte_addr];
				I2C0STX = pbuff[0];	
			
			}
			else {
				pbuff[i2c_cnt] = I2C0SRX;
				i2c_cnt++;	
			}		
	}
	
	// Slave Transmit
	else if ((status & 0x04)==0x04)   // Slave Transmit IRQ
	{
		i2c_cnt ++;
		I2C0STX = pbuff[i2c_cnt];
		I2C0ADR = 0xA1;
		//if(Byte_addr>=110 && Byte_addr<=113 && i2c_cnt==1)
			//set_DACs();	   			   		
	}
	
	else if((status & 0x0400)==0x0400)   // 
	{
		 first = 1;
		 //Write_Digital(2,1);
	}
	
	busy=1;
}
