Alvaro Cassinelli
/
skinGames_II
save loops
Embed:
(wiki syntax)
Show/hide line numbers
lockin.cpp
00001 #include "lockin.h" 00002 00003 Lockin lockin=Lockin();//pre-instanciation of object lockin with inter-file scope (declared extern in .h file) 00004 00005 00006 // NOTE: the ADC interrupt catching function is not a method of the Lockin class, hence the use of the pre-instantiated object "lockin": 00007 void catchInterupt(uint32_t value){ 00008 lockin.buffer_pos=(lockin.buffer_pos+1)%BUFFER_SIZE; 00009 lockin.buffer[lockin.buffer_pos] = (value>>4)&0xFFF; // this is 12 bit precision ADC (0 to 4095), can be stored in an "unsigned short" (two bytes) 00010 } 00011 00012 // PWM generation is configure as double edge 00013 // MR0 (Match Register 0) control the frequency 00014 // 'pwm2' uses MR1 and MR2 (rising and falling edges) 00015 // 'pwm4' uses MR3 and MR4 (rising and falling edges) 00016 // 'pwm1' and 'pwm3' cannot be used since they share the same Match Register 00017 // for the moment, all PWM pin are set as output: 00018 //PwmOut pwm1(p26); 00019 PwmOut pwm2(LOCKIN_LASER_PIN); //USED: this is pin p25, the LOCKIN_LASER_PIN 00020 PwmOut pwm3(p24); 00021 PwmOut pwm4(LOCKIN_REF_PIN); //USED: this is pin p23, the LOCKIN_REF_PIN 00022 //PwmOut pwm5(p22); 00023 //PwmOut pwm6(p21); 00024 00025 //Lockin::Lockin(){} 00026 00027 void Lockin::init(){ 00028 00029 //configure PWM for the laser and the Lockin 00030 refFreq = 147; 00031 offsetRef = 40; 00032 halfRefFreq = refFreq / 2; 00033 00034 refFrequency = 653; //init the lock-in frequency at 653 kHz 00035 phaseShiftLaser = 0.546; //offset of 54% for the laser signal 00036 phaseShiftLockin = 0; //no offset for the lock-in reference 00037 initPWM(); 00038 00039 //configure ADC: 00040 clearBuffer(); 00041 00042 // SET ADC IN BURST MODE: 00043 lockin.setADC_forLockin(1); 00044 } 00045 00046 void Lockin::setADC_forLockin(int mode) { 00047 if (mode>0) { // ADC BURST MODE: 00048 adc.startmode(0,0); 00049 adc.burst(1); 00050 adc.setup(LOCKIN_ADC_PIN, 1); 00051 adc.select(LOCKIN_ADC_PIN); 00052 adc.interrupt_state(LOCKIN_ADC_PIN, 1); 00053 adc.append(LOCKIN_ADC_PIN, catchInterupt); 00054 } else { 00055 // unset the lockin pin: 00056 adc.burst(0); 00057 adc.setup(LOCKIN_ADC_PIN, 0); 00058 adc.interrupt_state(LOCKIN_ADC_PIN, 0); 00059 } 00060 } 00061 00062 void Lockin::initPWM(){ 00063 00064 float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; // half shared periof 00065 _currentMR[0] = int(1.0 * MBEDFREQUENCY / refFrequency); //save the current value of MR0 (shared periof) //147 00066 _currentMR[1] = int(phaseShiftLaser * halfPeriod); //save the current value of MR1 //40 00067 _currentMR[2] = int(_currentMR[1] + halfPeriod); //save the current value of MR2 //40+73 00068 _currentMR[3] = int(phaseShiftLockin * halfPeriod); //save the current value of MR1 //0 00069 _currentMR[4] = int(_currentMR[3] + halfPeriod); //save the current value of MR2 //73 00070 00071 00072 // set PWM: 00073 LPC_PWM1->TCR = (1 << 1); // Reset counter, disable PWM 00074 LPC_SC->PCLKSEL0 &= ~(0x3 << 12); 00075 LPC_SC->PCLKSEL0 |= (1 << 12); // Set peripheral clock divider to /1, i.e. system clock 00076 00077 LPC_PWM1->PCR |= 0x0014; // Double edge PWM for PWM2,4 00078 00079 LPC_PWM1->MR0 = _currentMR[0]; // Match Register 0 is shared period counter for all PWM1 00080 00081 LPC_PWM1->MR1 = _currentMR[1]; // Match Register 1 is laser rising edge counter 00082 LPC_PWM1->MR2 = _currentMR[2]; // Match Register 2 is laser falling edge counter 00083 LPC_PWM1->MR3 = _currentMR[3]; // Match Register 3 is lock-in rising edge counter 00084 LPC_PWM1->MR4 = _currentMR[4]; // Match Register 4 is lock-in falling edge counter 00085 00086 LPC_PWM1->LER |= 1; // Start updating at next period start 00087 LPC_PWM1->TCR = (1 << 0) || (1 << 3); // Enable counter and PWM 00088 } 00089 00090 //change the frequency of the PWM after initPWM() 00091 void Lockin::setPWMFrequency(float freq){ 00092 refFrequency = freq; 00093 _currentMR[0] = int(MBEDFREQUENCY / refFrequency); //save the current value of MR0 00094 LPC_PWM1->MR0 = _currentMR[0]; //update PWM shared period register 00095 LPC_PWM1->LER |= 1; //update PWM 00096 } 00097 00098 //change the phase shift of the sensing laser after initPWM() 00099 void Lockin::setLaserPhaseShift(float phaseShift){ 00100 phaseShiftLaser = phaseShift; 00101 float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; 00102 _currentMR[1] = int(phaseShiftLaser * halfPeriod); //save the current value of MR1 00103 _currentMR[2] = _currentMR[1] + halfPeriod; //save the current value of MR2 00104 00105 LPC_PWM1->MR1 = _currentMR[1]; //update Laser rising edge match register 00106 LPC_PWM1->MR2 = _currentMR[2]; //update Laser faling edge match register 00107 } 00108 00109 //change the phase shift of the lock-in after initPWM() 00110 void Lockin::setLockinPhaseShift(float phaseShift){ 00111 phaseShiftLockin = phaseShift; 00112 float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; 00113 _currentMR[3] = int(phaseShiftLockin * halfPeriod); //save the current value of MR1 00114 _currentMR[4] = _currentMR[3] + halfPeriod; //save the current value of MR2 00115 00116 LPC_PWM1->MR3 = _currentMR[3]; //update lock-in rising edge match register 00117 LPC_PWM1->MR4 = _currentMR[4]; //update lock-in faling edge match register 00118 } 00119 00120 00121 void Lockin::setLaserPower(bool power){ 00122 if(power){ 00123 LPC_PWM1->MR1 = _currentMR[1]; 00124 LPC_PWM1->MR2 = _currentMR[2]; 00125 LPC_PWM1->LER |= 1; // update PWM at the next period 00126 } 00127 else{ 00128 LPC_PWM1->MR1 = 0; //set rising edge at 0 00129 LPC_PWM1->MR2 = 0; //set falling edge at 0 00130 LPC_PWM1->LER |= 1; // update PWM at the next period 00131 } 00132 } 00133 00134 void Lockin::clearBuffer(){ 00135 for(int i=0; i<BUFFER_SIZE; i++){ 00136 buffer[i] = 0; 00137 } 00138 buffer_pos = BUFFER_SIZE; 00139 } 00140 00141 /* 00142 void Lockin::catchInterupt(uint32_t value){ 00143 buffer_pos++; 00144 buffer_pos%=BUFFER_SIZE; 00145 buffer[buffer_pos] = value; 00146 } 00147 */ 00148 00149 //****** aquisition method *****// 00150 unsigned short Lockin::getLastValue(){ 00151 return buffer[buffer_pos]; 00152 } 00153 00154 unsigned short Lockin::getSmoothValue(){ 00155 unsigned short smoothValue = buffer[0]; 00156 for(int i=1; i<BUFFER_SIZE; i++){ 00157 smoothValue += buffer[i]; 00158 } 00159 smoothValue = (unsigned short)(smoothValue/BUFFER_SIZE); // note: we could have more precision (sub-12 bit), but it's not required and would imply using a float as output 00160 00161 return smoothValue; 00162 } 00163 00164 unsigned short Lockin::getMedianValue(){ 00165 //this method applies a median filter to the buffer 00166 //It reduces the salt-and-pepper noise 00167 //It seems that this noise is very strong on certain mBed board, but not all... 00168 00169 // unsigned short orderedBuffer[BUFFER_SIZE_MEDIAN]; 00170 00171 //sort half of the buffer: 00172 00173 //copy buffer 00174 for(int i=0; i<BUFFER_SIZE_MEDIAN; i++){ 00175 orderedBuffer[i] = buffer[(buffer_pos+BUFFER_SIZE-i+DELAY_BUFFER_MEDIAN)%BUFFER_SIZE]; 00176 } 00177 00178 //order buffer 00179 for(int i=0; i<BUFFER_SIZE_MEDIAN-1; i++){ 00180 int minPos = i; 00181 00182 //get min 00183 for(int j=i+1; j<BUFFER_SIZE_MEDIAN; j++){ 00184 if(orderedBuffer[j] < orderedBuffer[minPos]) minPos = j; 00185 } 00186 00187 //swap min to the right position 00188 if(minPos != i){ 00189 int tmpMin = orderedBuffer[minPos]; 00190 orderedBuffer[minPos] = orderedBuffer[i]; 00191 orderedBuffer[i] = tmpMin; 00192 } 00193 } 00194 00195 return orderedBuffer[BUFFER_SIZE_MEDIAN/2]; 00196 }
Generated on Tue Jul 12 2022 21:23:04 by 1.7.2