-

Camera.cpp

Committer:
Deurklink
Date:
2014-07-04
Revision:
0:9719776f6e46

File content as of revision 0:9719776f6e46:

#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-------------------------------------