save loops

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lockin.cpp Source File

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 }