Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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-------------------------------------