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

Revision:
0:4b5874bff9bb
Child:
1:4284f27d638d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Flipper.h	Mon Jul 14 09:35:12 2014 +0000
@@ -0,0 +1,178 @@
+#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
\ No newline at end of file