/* v1.0 "int" is used for the ADC and DAC data although it should be unsigned, it should be not a problem at all as this data are limited to 12bits... */ #include #include #include #include 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 start, stop,start_gnd,stop_gnd,start2,stop2,Vset,wf_len, step_max,N; unsigned char transf,enab_gnd; unsigned int trigg_cnt; float Gain; //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, tg_cnt; 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 int k; unsigned short Data[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 = 50; // number of measume,ts for averaging Vin = 0; // initialize the voltage of first step Vmean = 2000; start = 20; stop = 30; start_gnd = 0; stop_gnd = 10; wf_len = 256; Vset = 10; 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 %s\ncompiled: %s\nbecause we can!",__func__,__DATE__); for (k=0;k<4;k++){ plist[100+k] = (unsigned char*)(Vout+k); } // 104 // 105 plist[120] = (unsigned char*)&I2C0ID0; plist[121] = (unsigned char*)&ADCCP; 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; tg_cnt = 0; cnt_N = 0; enab_gnd = 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){ armed = 0; //*** aquisition of the waveform *** for(k=0;k>16; // read voltage from ADC0 } tg_cnt++; //*** copy for the i2c *** while(transf==1){} // we make sure that the data are not changed during the transfer memcpy(BigDat,Data,256*sizeof(short)); trigg_cnt = tg_cnt; if (cnt_N==0){ sum = 0; // initialization of the measurement sum_gnd = 0; } cnt_N++; //sum of the data for(k=start;k=N){ Vin = sum/(cnt_N*(stop-start)); // calculate average value Vin_gnd = sum_gnd/(cnt_N*(stop_gnd-start_gnd)); // calculate average value } //*** feedback *** (mode is on pin p0.6) // LOCK MODE if((((GP0DAT&0x000000FF)>>6)&0x1)==1){ if(cnt_N>=N){ cnt_N=0; //cnt_gnd=0; step = (Vset-Vin+Vin_gnd*enab_gnd)*Gain; if (step>step_max) step = step_max; else if (step<-step_max) step = -step_max; Vout2 = Vout2 + step; if(Vout2>4095){ Write_Digital(0,1); Vout2 = 4090; } else{ Write_Digital(0,0); } } } // LEARN MODE // we set the outputs to the average voltage // and save the current input level as the set point of the next locking enable else{ if(cnt_N>=N){ Vset = Vin-Vin_gnd*enab_gnd; cnt_N=0; } Vout2 = Vmean; } //this line could also be inserted in the if conditions and thus not set every loops DAC2DAT = DATtoADC(Vout2); // output voltage } } } int main(void) { lock_StabPulse_i2c(); return 0; } /*************************************************/ /*************************************************/ /************ IRQ Service Routine *************/ /*************************************************/ /*************************************************/ void My_IRQ_Handler() { int status = I2C0SSTA; // 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); } // either we transfer a waveform or some parameters // and when it is done we should put back transf = 0 /*if((i2c_cnt>31 && Byte_addr==15) || (i2c_cnt>1 && Byte_addr>15)){ Write_Digital(2,1); transf = 0; } */ /*if(i2c_cnt>31 && Byte_addr==15){ Write_Digital(2,1); transf = 0; }*/ }