synch the camera trigger with the signal in phase and quadrature (every frame or every N frames). We can also simulate the product by the in-phase signal (with a small arbitrary phase difference)

Dependencies:   mbed

Flipper.h

Committer:
mbedalvaro
Date:
2014-07-14
Revision:
0:4b5874bff9bb
Child:
1:4284f27d638d

File content as of revision 0:4b5874bff9bb:

#ifndef Flipper_h
#define Flipper_h

#include "mbed.h"

#define shutterPin p21 // for tests
#define  ledPin p22 // the actual modulation of the LED source (equal to PHASE or QUAD signal every N frames)
#define  cameraTriggerPin p23

// A class for flip()-ing a DigitalOut using a timer

//1) Class for toggling the LED (in phase or quadrature, with a multiplier)
class Flipper {
public:
    static DigitalOut _pin;
    static bool state;
    static bool multiplier;//=true; // this is for simulating the deconvolution
    // NOTE initialization needs to be in the cpp file, unless it's a const 
    
    static void delay90() {state = !state; _pin=state;}
    static void multImmediate() { _pin=state&&multiplier;}
 

    Flipper(PinName pin, unsigned int interval): us_interval(interval) {
        Flipper::_pin=pin;
        state=true;
        _pin=state;
    }
    
    void start() {
        myTicker.attach_us(this, &Flipper::flip, us_interval); // the address of the object, member function, and interval
    }
    
   void stop() {
        myTicker.detach();
    }
    
    void flip() {
        state = !state;
        _pin=state&&multiplier;
    }
    
private:
    unsigned int us_interval;
    Ticker myTicker;
};

// 2) Camera trigger class (NOTE: we are using MODE 2 of Point gray, meaning we control the exposure)
class Trigger {
   
  friend class Flipper; // because we will call delay90() method

  public:
  
    enum triggerState {
        WAITING=0, 
        EXPOSE, 
        NUM_STATES
        };
  
    Trigger(PinName pin, float fps, unsigned int exposure) : _pin(pin) {
    _pin=1;
    us_exposureTime=exposure;
    us_waitingTime=(unsigned int)(1000000.0/fps-us_exposureTime);
    framesQPToggle=2; // default number of frames before toggling between Q and P signals (delaying the Flipper signal by 90 deg). 
    QP_Mode=true;
    }
    
    void setQPToggleFrames(unsigned int numToggleQPFrames) {
        framesQPToggle=numToggleQPFrames;
    }
    
    void setFrameRate(float fps) {
        us_waitingTime=(unsigned int)(1000000.0/fps-us_exposureTime);
    }
    
     void setExposure(unsigned int exposure) {
        us_exposureTime=exposure;
    }
    
    void start() {
        // We start in WAITING and go to EXPOSE
        myTimer.attach_us(this, &Trigger::trigger, us_waitingTime); // the address of the object, member function, and interval
        myTriggerState=WAITING;
        frameCounter=0;
    }
    
    void toggleQP(bool mode) {
        QP_Mode=mode;
        }
    
   void stop() {
        myTimer.detach();
    }
    
    void trigger() {
        switch(myTriggerState) {
            case WAITING: // if the state was "wait" and we got here, we need to start exposing:
                _pin=0; // a high-low change triggers the camera
                // now we need to reset the timeout and give it another value:
                myTimer.attach_us(this, &Trigger::trigger, us_exposureTime);
                myTriggerState=EXPOSE;
            break;
                case EXPOSE: // if the state was EXPOSE, we need to stop exposing and go to wait:
                _pin=1; // a low-high stop exposing 
                // now we need to reset the timeout and give it another value:
                myTimer.attach_us(this, &Trigger::trigger, us_waitingTime);
                myTriggerState=WAITING;
                
                 // Also, this means we acquired ONE frame...
                 // Switch the from phase to quadrature int the friend class Flipper, every N frames (if we want):
                frameCounter=(frameCounter+1)%framesQPToggle;
                if (QP_Mode&&frameCounter==0) {
                    //Flipper::state = ! Flipper::state ; // this correspond to calling the flip function (but without multiplier)
                    Flipper::delay90();
                }
            break;
            default:
            break;
            }
    }
    
    private:
     DigitalOut _pin;
     bool QP_Mode; // this is to select toggling or not
     triggerState myTriggerState;
     unsigned int frameCounter;
     unsigned int framesQPToggle;
     unsigned int us_exposureTime, us_waitingTime;
     Timeout myTimer; // I need to use a timeout, and not a ticker because the intervals are different for the trigger period and exposure time
};

// 3) The simulation of the LCD shutter:
class Shutter{
    friend class Flipper; // because we will modify the Flipper variable "multiplier"

public:
    // Note: we don't really need a toggling pin for this, but it can be good to see it on the oscilloscope
    Shutter(PinName pin, unsigned int interval) : _pin(pin), us_interval(interval) {
        state=true;
        _pin=state;
        mix=true;
    }
    
    void start() {
        myTicker.attach_us(this, &Shutter::flip, us_interval); // the address of the object, member function, and interval
    }
    
   void mixSignal(bool mode) {
        mix=mode;
        } 
    
   void stop() {
        myTicker.detach();
    }
    
    // the shutter "flip" function also affect the friend variable "multiplier":
    void flip() {
        state = !state;
        _pin=state;
        if (mix) {
            Flipper::multiplier=state;
            } 
        else {
            Flipper::multiplier=true;
            }
        Flipper::multImmediate();
    }
    
private:
    bool mix; // this is for mixing this signal with the led (ie, product)
    bool state;
    DigitalOut _pin;
    unsigned int us_interval;
    Ticker myTicker;
};

#endif