-

Revision:
0:9719776f6e46
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Camera.cpp	Fri Jul 04 09:48:47 2014 +0000
@@ -0,0 +1,343 @@
+#include "Camera.h"
+
+Camera::Camera(PinName gpsTx, PinName gpsRx, PinName xbTx, PinName xbRx, int freq, int len, int cdelay) : 
+    gps(gpsTx, gpsRx), 
+    L1(LED1),
+    L2(LED2),
+    L3(LED3),
+    L4(LED4),
+    XBee(xbTx, xbRx),
+    PPS(p5),
+    T1(p11),
+    T2(p12),
+    T3(p15),
+    T4(p16),
+    T5(p17),
+    T6(p18),
+    T7(p19),
+    T8(p20),
+    B1(p24),
+    B2(p23),
+    B3(p22),
+    B4(p21),
+    PulseFrequency(freq),
+    Pulselength(len),
+    CameraDelay_us(cdelay)
+{
+    PWMon = false;
+    RxTO = false;
+}
+
+// Beacon initialisation
+bool Camera::init(){
+    
+    // Power down ethernet module
+    PHY_PowerDown();
+    
+    // Initialize dipswitches
+    initDipSwitch();
+    
+    // Read beacon number and timing offset
+    readDipSwitch();
+    
+    // Set baud rate
+    XBee.baud(9600);
+    
+    XBee.printf("\r\n.. Camera (ID:%d) Initializing ..\n",BeaconNumber);
+
+    // Initialize GPS unit
+    gps.Init();
+    
+    //Attach interrupt to rising edge of GPS PPS pin
+    PPS.rise(this, &Camera::ppsSync);
+    
+    // Initialize PWM
+    resetPWM(PulseFrequency, Pulselength);
+
+    XBee.printf("\r\n.. Camera (ID:%d) Initialization finished ..\n",BeaconNumber);
+    
+    L1 = 1;
+    
+    return true;
+}
+
+void Camera::cameraDelay(){
+    // Reset PWM timer value so that new cycle immediately starts
+    LPC_PWM1->TC = Period*24+TimingOffset - 1;
+}
+
+
+// PPS pin interrupt
+void Camera::ppsSync(){
+    // Toggle LED1
+    L1 = !L1; 
+    if (PWMon == true){
+        // Call timer reset function for PWM after CameraDelay_us microseconds
+        _CameraDelay.attach_us(this,&Camera::cameraDelay,CameraDelay_us);
+    }
+}  
+
+// XBee Receive Timeout
+void Camera::rxTimeOut(){
+    RxTO = true;
+}
+
+
+//------------------------------------DIP-SWITCHES---------------------------
+void Camera::readDipSwitch(){
+    // Transform the dip switch binary numbers into integers
+    // For the timing offset, the leftmost bit is the sign bit (2's complement)
+    TimingOffset = -128*T1 + 64*T2 + 32*T3 + 16*T4 + 8*T5 + 4*T6 + 2*T7 + T8;
+    BeaconNumber = 8*B1 + 4*B2 + 2*B3 + B4;
+}
+
+void Camera::initDipSwitch(){
+    // Set pull-down resistor for dip switch inputs
+    T1.mode(PullDown);
+    T2.mode(PullDown);
+    T3.mode(PullDown);
+    T4.mode(PullDown);
+    T5.mode(PullDown);
+    T6.mode(PullDown);
+    T7.mode(PullDown);
+    T8.mode(PullDown);
+    
+    B1.mode(PullDown);
+    B2.mode(PullDown);
+    B3.mode(PullDown);
+    B4.mode(PullDown);   
+}
+//---------------------------------------------------------------------------
+
+
+//------------------------------------PWM------------------------------------
+void Camera::startPWM(){
+    // enable PWM mode and counting
+    LPC_PWM1->TCR = (1 << 3) | 1;  
+    PWMon = true;
+}
+
+void Camera::stopPWM(){
+    // Reset PWM-counter; this also stops it
+    LPC_PWM1->TCR = 2; 
+    PWMon = false;
+}
+
+void Camera::resetPWM(int _PulseFrequency, int _Pulselength){
+    // Note: wherever you read pin P2.0, it is pin 2[0] of the microcontroller.
+    // This is wired to p26 of the mbed board.
+    stopPWM();
+    // First stop PWM if it is running
+    
+    PWMclock = SystemCoreClock / 96;
+    Period = PWMclock / _PulseFrequency; 
+    
+    
+    LPC_SC->PCONP |= 1 << 6;
+    // Reset mode PWM timer
+    LPC_PWM1->TCR = 2; 
+    
+    // configure P2.0 for PWM1.1 - O - Pulse Width Modulator 1, channel 1 output.
+    LPC_PINCON->PINSEL4 = (LPC_PINCON->PINSEL4 & ~(0x3 << 0)) | (0x1 << 0);
+    
+    // Disable pullups for P2.0
+    LPC_PINCON->PINMODE4 = (LPC_PINCON->PINMODE4 & ~0x3) | 0x2;
+
+    // Set prescaler
+    //LPC_PWM1->PR = SystemCoreClock / (4 * 1000000) - 1; 
+    
+    // Set up match registers
+    LPC_PWM1->MR0 = Period*24+TimingOffset;     // Set MR0 (Period)  
+    /*
+       TimingOffset is there to compensate for crystal errors.
+       It has to be calculated for every mbed, as every crystal is a little different
+       It basically adds or detracts a few cycles from every period to keep the period equal for every module
+    */
+    LPC_PWM1->MR1 = _Pulselength*24; // Set MR1 (Pulse length)
+    LPC_PWM1->LER = 0x07;       // set latch-enable register
+    LPC_PWM1->MCR |= 0x02;      // Reset PWM1 on match
+    LPC_PWM1->PCR = 1 << 9;     // enable PWM1 with single-edge operation
+}
+//------------------------------------/PWM------------------------------------
+
+
+
+//------------------------------------XBee------------------------------------
+bool Camera::xbeeReadable(){
+    return XBee.readable();
+}
+    
+void Camera::printStatus(){
+    // Print the status of a Beacon
+    XBee.printf("\r\n\nCamera (ID:%d); TimingOffset: %d",BeaconNumber, TimingOffset);
+    XBee.printf("\r\nLast GPS update: %d:%d:%2.2f",gps.hours, gps.minutes, gps.seconds);
+    XBee.printf("\r\nFlash frequency: %d Hz; Pulse length: %d usec; Delay: %d usec", PulseFrequency, Pulselength, CameraDelay_us);
+    XBee.printf("\r\nPulse generation: %d (0=off,1=on)",PWMon);
+    XBee.printf("\r\nGPS location: %f,%f", gps.latitude, gps.longitude);
+    XBee.printf("\r\nFixtype: %d (0=no fix,1=gps,2=differential)",gps.fixtype);
+    XBee.printf("\r\nNo. of satellites: %d",gps.satellites);
+}
+
+void Camera::getXbeeData(){
+    // Function used by parse data function
+    // Read data from the Xbee serial Buffer
+    // Wait until $ is read, then put characters received after that in RxBuffer[] until # is read.
+    
+    RxTO = false; // Reset time-out
+    bool dollarSignRcv = false;
+    bool dashRcv = false;
+    
+    _RxTimeOut.attach(this,&Camera::rxTimeOut,XBEETIMEOUT); // timeout after XBEETIMEOUT seconds
+    
+    while(!dollarSignRcv){
+        // Read XBee until dollarsign received or timeout
+        if (XBee.readable()){
+            if (XBee.getc() == '$'){
+                dollarSignRcv = true;
+                //XBee.printf("$ received");
+            }
+        }
+        // Timeout if no $ is received within XBEETIMEOUT seconds
+        if (RxTO == true){
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) rx time out",BeaconNumber);
+            return;
+        }
+    }
+    
+    int i = 0;
+    while(!dashRcv){
+        // Fill buffer until dash is received, buffer is full or timeout
+        if (XBee.readable()){
+            RxBuffer[i] = XBee.getc();
+            if(RxBuffer[i] == '#') {
+                RxBuffer[i] = 0;
+                dashRcv = true;
+                //XBee.printf("# received");
+            }
+            i++;
+        }
+        // Return if buffer is full
+        if (i > 255){
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) rx buffer overflow",BeaconNumber);
+            return;
+        }
+        // Timeout if no '#' is received within XBEETIMEOUT seconds
+        if (RxTO == true){
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) rx time out",BeaconNumber);
+            XBee.printf("\r\nReceived: %s",RxBuffer);
+            return;
+        }
+    }
+}
+
+void Camera::parseXbee(){
+    // This function collects data from RxBuffer[] and reads it
+    
+    // put data into RxBuffer[]
+    getXbeeData();   
+     
+    // $STATUS#
+    // Send a status message
+    if (strncmp(RxBuffer, "STATUS",6) == 0){
+        wait(BeaconNumber);
+        printStatus();
+    }
+    
+    // $STARTPULSE#
+    // Start pulse generation if there is a GPS fix
+    else if (strncmp(RxBuffer, "STARTPULSE",10) == 0){
+        if (gps.fixtype > 0){
+            startPWM();
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) pulses started",BeaconNumber);
+        }
+        else{
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) has no GPS fix",BeaconNumber);
+        }   
+    }
+    
+    // $FORCEPULSE#
+    // Start pulse generation regardless of GPS fix
+    else if (strncmp(RxBuffer, "FORCEPULSE",10) == 0){
+        startPWM();
+        if (gps.fixtype > 0){
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) pulses started",BeaconNumber);
+        }
+        else{
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) has no GPS fix; pulses started anyway",BeaconNumber);
+        }   
+    }   
+      
+    // $STOPPULSE#
+    // Stop pulse generation
+    else if (strncmp(RxBuffer, "STOPPULSE",9) == 0){
+        if (PWMon == true){
+            stopPWM();
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) pulses stopped",BeaconNumber);
+        }
+        else{
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) has not been started yet. No action",BeaconNumber);
+        }
+    }
+    
+    // $CHANGEPULSE,freq(hz),pulselength(us)#
+    // Change frequency and pulse length; Ignored by camera
+    else if (strncmp(RxBuffer, "CHANGEPULSE",11) == 0){ 
+        wait(BeaconNumber);
+        XBee.printf("\n\rCamera (ID:%d) ignored message",BeaconNumber);
+    }
+    
+    // $CAMCHANGEPULSE,freq(hz),pulselength(us),delay(us)#
+    // Change frequency and pulse length of camera
+    else if (strncmp(RxBuffer, "CAMCHANGEPULSE",14) == 0){
+        if(sscanf(RxBuffer, "%*s %d %d %d", &PulseFrequency, &Pulselength, &CameraDelay_us) ==3){
+            resetPWM(PulseFrequency, Pulselength);
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) frequency  set to: %d Hz. Pulselength set to %d us. Delay set to %d us",BeaconNumber,PulseFrequency,Pulselength,CameraDelay_us);
+            XBee.printf("\r\nWaiting for start pulse command");
+        }
+        else{
+            wait(BeaconNumber);
+            XBee.printf("\r\nCamera (ID:%d) pulselength, frequency or delay not received correctly, please try again (CAMCHAMGEPULSE,freq,pulselength,delay)",BeaconNumber);
+        }
+    }
+    
+    // $RESETPULSE#
+    // Read the dip switches, stop and reset PWM with new timing offset
+    else if (strncmp(RxBuffer, "RESETPULSE",10) == 0){
+        readDipSwitch();
+        resetPWM(PulseFrequency, Pulselength);
+        wait(BeaconNumber);
+        XBee.printf("\r\nCamera (ID:%d) PWM reset",BeaconNumber);
+    }
+    
+    // Received message was not one of the above commands
+    else{
+        wait(BeaconNumber);
+        XBee.printf("\r\nCamera (ID:%d) did not understand message",BeaconNumber);
+        XBee.printf("\r\nReceived: %s",RxBuffer);
+    }
+    // Flush buffer
+    for (int i=0;i<255;i++){
+        RxBuffer[i] = '0';
+    }
+}
+//-----------------------------------/XBee------------------------------------
+
+//------------------------------------GPS-------------------------------------
+bool Camera::gpsReadable(){
+    return gps.readable();
+}
+
+void Camera::parseGpsData(){
+    gps.parseData();
+}
+//-----------------------------------/GPS-------------------------------------