Hardware IO control: mirrors, lock in
Diff: lockin.cpp
- Revision:
- 0:c19dc1d8b225
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lockin.cpp Mon Oct 17 13:23:06 2011 +0000 @@ -0,0 +1,148 @@ +#include "lockin.h" + +Lockin lockin=Lockin();//pre-instanciation of object lockin with inter-file scope (declared extern in .h file) + +void catchInterupt(uint32_t value){ + lockin.buffer_pos=(lockin.buffer_pos+1)%BUFFER_SIZE; + lockin.buffer[lockin.buffer_pos] = (value>>4)&0xFFF; // this is 12 bit precision ADC (0 to 4095) +} + +// PWM generation is configure as double edge +// MR0 (Match Register 0) control the frequency +// 'pwm2' uses MR1 and MR2 (rising and falling edges) +// 'pwm4' uses MR3 and MR4 (rising and falling edges) +// 'pwm1' and 'pwm3' cannot be used since they share the same Match Register +// for the moment, all PWM pin are set as output: +PwmOut pwm1(p26); +PwmOut pwm2(p25); //also defined as LOCKIN_LASER_PIN +PwmOut pwm3(p24); +PwmOut pwm4(p23); //also defined as LOCKIN_REF_PIN +PwmOut pwm5(p22); +PwmOut pwm6(p21); + +//Lockin::Lockin(){} + +void Lockin::init(){ + + //configure PWM for the laser and the Lockin + refFreq = 147; + offsetRef = 40; + halfRefFreq = refFreq / 2; + + refFrequency = 653; //init the lock-in frequency at 653 kHz + phaseShiftLaser = 0.546; //offset of 54% for the laser signal + phaseShiftLockin = 0; //no offset for the lock-in reference + initPWM(); + + //configure ADC: + clearBuffer(); + + adc.startmode(0,0); + adc.burst(1); + adc.setup(LOCKIN_ADC_PIN, 1); + adc.select(LOCKIN_ADC_PIN); + adc.interrupt_state(LOCKIN_ADC_PIN, 1); + adc.append(LOCKIN_ADC_PIN, catchInterupt); +} + + +void Lockin::initPWM(){ + + float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; // half shared periof + _currentMR[0] = int(1.0 * MBEDFREQUENCY / refFrequency); //save the current value of MR0 (shared periof) //147 + _currentMR[1] = int(phaseShiftLaser * halfPeriod); //save the current value of MR1 //40 + _currentMR[2] = int(_currentMR[1] + halfPeriod); //save the current value of MR2 //40+73 + _currentMR[3] = int(phaseShiftLockin * halfPeriod); //save the current value of MR1 //0 + _currentMR[4] = int(_currentMR[3] + halfPeriod); //save the current value of MR2 //73 + + + // set PWM: + LPC_PWM1->TCR = (1 << 1); // Reset counter, disable PWM + LPC_SC->PCLKSEL0 &= ~(0x3 << 12); + LPC_SC->PCLKSEL0 |= (1 << 12); // Set peripheral clock divider to /1, i.e. system clock + + LPC_PWM1->PCR |= 0x0014; // Double edge PWM for PWM2,4 + + LPC_PWM1->MR0 = _currentMR[0]; // Match Register 0 is shared period counter for all PWM1 + + LPC_PWM1->MR1 = _currentMR[1]; // Match Register 1 is laser rising edge counter + LPC_PWM1->MR2 = _currentMR[2]; // Match Register 2 is laser falling edge counter + LPC_PWM1->MR3 = _currentMR[3]; // Match Register 3 is lock-in rising edge counter + LPC_PWM1->MR4 = _currentMR[4]; // Match Register 4 is lock-in falling edge counter + + LPC_PWM1->LER |= 1; // Start updating at next period start + LPC_PWM1->TCR = (1 << 0) || (1 << 3); // Enable counter and PWM +} + +//change the frequency of the PWM after initPWM() +void Lockin::setPWMFrequency(float freq){ + refFrequency = freq; + _currentMR[0] = int(MBEDFREQUENCY / refFrequency); //save the current value of MR0 + LPC_PWM1->MR0 = _currentMR[0]; //update PWM shared period register + LPC_PWM1->LER |= 1; //update PWM +} + +//change the phase shift of the sensing laser after initPWM() +void Lockin::setLaserPhaseShift(float phaseShift){ + phaseShiftLaser = phaseShift; + float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; + _currentMR[1] = int(phaseShiftLaser * halfPeriod); //save the current value of MR1 + _currentMR[2] = _currentMR[1] + halfPeriod; //save the current value of MR2 + + LPC_PWM1->MR1 = _currentMR[1]; //update Laser rising edge match register + LPC_PWM1->MR2 = _currentMR[2]; //update Laser faling edge match register +} + +//change the phase shift of the lock-in after initPWM() +void Lockin::setLockinPhaseShift(float phaseShift){ + phaseShiftLockin = phaseShift; + float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; + _currentMR[3] = int(phaseShiftLockin * halfPeriod); //save the current value of MR1 + _currentMR[4] = _currentMR[3] + halfPeriod; //save the current value of MR2 + + LPC_PWM1->MR3 = _currentMR[3]; //update lock-in rising edge match register + LPC_PWM1->MR4 = _currentMR[4]; //update lock-in faling edge match register +} + + +void Lockin::setLaserPower(bool power){ + if(power){ + LPC_PWM1->MR1 = _currentMR[1]; + LPC_PWM1->MR2 = _currentMR[2]; + LPC_PWM1->LER |= 1; // update PWM at the next period + } + else{ + LPC_PWM1->MR1 = 0; //set rising edge at 0 + LPC_PWM1->MR2 = 0; //set falling edge at 0 + LPC_PWM1->LER |= 1; // update PWM at the next period + } +} + +void Lockin::clearBuffer(){ + for(int i=0; i<BUFFER_SIZE; i++){ + buffer[i] = 0; + } + buffer_pos = BUFFER_SIZE; +} + +/* +void Lockin::catchInterupt(uint32_t value){ + buffer_pos++; + buffer_pos%=BUFFER_SIZE; + buffer[buffer_pos] = value; +} +*/ + +float Lockin::getSmoothValue(){ + float smoothValue = buffer[0]; + for(int i=1; i<BUFFER_SIZE; i++){ + smoothValue += buffer[i]; + } + smoothValue /= BUFFER_SIZE; + + return smoothValue; +} + +float Lockin::getLastValue(){ + return buffer[buffer_pos]; +}