-
Diff: Camera.cpp
- 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-------------------------------------