Hardware IO control: mirrors, lock in

lockin.cpp

Committer:
mbedalvaro
Date:
2011-10-17
Revision:
0:c19dc1d8b225

File content as of revision 0:c19dc1d8b225:

#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];
}