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