Changes to allow hardware camera trigger
Fork of GPS_Incremental by
main.cpp
- Committer:
- dannyman939
- Date:
- 2013-04-18
- Revision:
- 10:078891935385
- Parent:
- 9:13724ed3f825
File content as of revision 10:078891935385:
#include "mbed.h"
#include <string>
//set up the message buffer to be filled by the GPS read process
#define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 256
#include "MODSERIAL.h"
#include "SDFileSystem.h" //imported using the import utility
//general digital I/O specifications for this application
//SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name);
SDFileSystem sd(p11,p12,p13,p14,"sd");
DigitalIn sd_detect(p27);
DigitalOut ppsled(LED1); //blink an LED at the 1PPS
DigitalOut trig1led(LED2); //blink an LED at the camera trigger detection
DigitalOut recordDataled(LED4); //set the led when the record is on
//InterruptIn camera1Int(p30); // camera interrupt in
DigitalOut camera2Pin(p29); // We dont use the second camera interrupt
//USB serial data stream back to the PC
Serial toPC(USBTX, USBRX); //connect the GPS TX, RX to p9 and p10
bool detectedGPS1PPS = false; //flag set in the ISR and reset after processing the 1PPS event
int PPSCounter = 0; //counts the 1PPS occurrences
int byteCounter = 0; //byte counter -- zeroed at 1PPS
unsigned short perSecMessageCounter=0; //counts the number of messages in a sec based on the header detection
bool lookingForMessages = true; //set in the PPS ISR and set false after the message processing in the main
bool messageDetected = false; //have detected a message header
unsigned long IMUbytesWritten = 0; //counts the IMU bytes written by the fwrite() to the SD card
int savedByteCounter = 0; //save ByteCounter at the 1PPS for display in main
int savedPerSecMessageCounter=0; //saved PerSecMsgCounter for display in main
int IMUClockCounter = 0; //counter for IMU samples per sec
int savedIMUClockCounter=0; //saved at the 1PPS for later diaplay from main
bool camera1EventDetected = false; //flag from ISR indicating a clock event occurred
double camera1Time; //GPS time of the camera event
int TotalBadCRCmatches = 0; //counter for the bad CRC matches for all GPS messages
//////////////////////////////////////////////////////////////////////
// the below should become classes
//////////////////////////////////////////////////////////////////////
#include "OEM615.h" //OEM615 GPS activities
#include "ADIS16488.h" //ADIS16488 activities
#include "PCMessaging.h" //PC messaging activities
//ISR for detection of the GPS 1PPS
void detect1PPSISR(void)
{
timeFromPPS.reset(); //reset the 1PPS timer upon 1PPS detection
savedIMUClockCounter = IMUClockCounter; //number of IMU clocks received since last 1PPS
savedByteCounter = byteCounter; //save byteCounter for display in main
savedPerSecMessageCounter = perSecMessageCounter; //save for display un main
IMUClockCounter = 0; //counts per-sec IMU samples (between 1PPS events)
byteCounter = 0; //countes bytes between 1PPS events
perSecMessageCounter = 0; //counts GPS messages between 1PPS events
GPS_COM1.rxBufferFlush(); //flush the GPS serial buffer
detectedGPS1PPS = true; //set false in the main when 1PPS actions are complete
lookingForMessages = true; //set false in main after processing messages
PPSCounter++; //count number of 1PPS epoch
//note -- the below accounts for time information becoming available AFTER the 1PPS event
PPSTimeOffset++; //counts 1PPS events between matching POS and VEL messages
ppsled = !ppsled; //blink an LED at the 1PPS
};
//ISR for detection of the hotshoe trigger 1
//void camera1ISR(void)
//{
//GPSTime is from POS message header
//PPSTimeOffset is an even sec to account for Time becoming known AFTER the 1PPS
//PPSTimeOffset + timeFromPPS.read() can be as large as 1.02 secs
// camera1Time = GPSTime + PPSTimeOffset + timeFromPPS.read();
// camera1EventDetected = true; //reset to false in main after processing the image detection
// trig1led = !trig1led; //blink an LEWD at the camera event detection
//};
///////////////////////////////////////////////////////
//set up the USB port and the GPS COM port
///////////////////////////////////////////////////////
FILE *fpNav = NULL; //file pointer to the nav file on the SD card
void setupCOM(void)
{
//system starts with GPS in reset active
//dis-engage the reset to get the GPS started
GPS_Reset=1; wait_ms(1000);
//establish 1PPS ISR
PPSInt.rise(&detect1PPSISR);
//set the USB serial data rate -- rate must be matched at the PC end
//This the serial communication back to the the PC host
//Launch the C++ serial port read program there to catch the ASCII characters
//toPC.baud(9600); wait_ms(100);
toPC.baud(8*115200); wait_ms(100);
//toPC.baud(1*115200); wait_ms(100);
toPC.printf("\n\n released GPS from RESET and set to high baud rate \n\n");
//just wait to launch the GPS receiver
for (int i=0; i<5; i++) { toPC.printf(" to start: %3d \n", 4-i); wait(1); }
sd_detect.mode(PullUp);
if (sd_detect == 0)
{
mkdir("/sd/Data", 0777);
}
else
{
toPC.printf(" SD card not present \n");
}
//NOTE: we do not assume that the GPS receiver has been pre-set up for the WALDO_FCS functionality
//we alwsys start with a reset and reprogram the receiver with our data out products
// this prevents failure because of a blown NVRAM as occurred for the older camera systems
//this is the COM1 port from th GPS receiuver to the mbed
//it should be always started at 9600 baud because thats the default for the GPS receiver
GPS_COM1.baud(9600); wait_ms(100);
// this ASCII command sets up the serial data from the GPS receiver on its COM1
char ch7[] = "serialconfig COM1 9600 n 8 1 n off";
// this is a software reset and has the same effect as a hardware reset (why do it?)
//char ch0[] = "RESET";
//this command stops all communication from the GPS receiver on COM1
//logs should still be presented on USB port so the Novatel CDU application can be used on the PC in parallel
char ch1[] = "unlogall COM1";
//set the final baud rate that we will use from here
//allowable baud rate values: 9600 115200 230400 460800 921600
//char ch2[] = "serialconfig COM1 921600 n 8 1 n off";
char ch2[] = "serialconfig COM1 460800 n 8 1 n off";
//the below commands request the POS, VEL, RANGE, and TIME messages
char ch3[] = "log COM1 BESTPOSB ONTIME 1"; //messageID = 42
char ch4[] = "log COM1 BESTVelB ONTIME 1"; //messageID = 99
char ch5[] = "log COM1 RANGEB ONTIME 1"; //messageID = 43
//char ch6[] = "log COM1 TIMEB ONTIME 1"; //messageID = 101
//set up VARF to be 100Hz with 1X10^4 * 10^-8 = 10^-4 sec (10usec) pulse width
//in fact, we do not use this output but it is available.
//originally planned to use this to command the IMU data
//char ch8[] = "FREQUENCYOUT enable 10000 1000000";
toPC.printf("set serial config \n");
sendASCII(ch7, sizeof(ch7)); wait_ms(500);
//sendASCII(ch0, sizeof(ch0));
toPC.printf("unlog all messages \n");
sendASCII(ch1, sizeof(ch1)); wait_ms(500);
toPC.printf("log BESTPOSB on COM1 \n");
sendASCII(ch3, sizeof(ch3)); wait_ms(500);
toPC.printf("log BESTVELB on COM1\n");
sendASCII(ch4, sizeof(ch4)); wait_ms(500);
toPC.printf("log RANGEB on COM1\n");
sendASCII(ch5, sizeof(ch5)); wait_ms(500);
//toPC.printf("log TIMEB om COM1 \n");
//sendASCII(ch6, sizeof(ch6)); wait_ms(100);
//toPC.printf("Set up th VARF signal \n");
//sendASCII(ch8, sizeof(ch8)); wait_ms(500);
//set GPS output COM1 to the final high rate
toPC.printf("set the COM ports to high rate\n");
sendASCII(ch2, sizeof(ch2)); wait_ms(500);
//set the mbed COM port to match the GPS transmit rate
//the below baud rate must match the COM1 rate coming from the GPS receiver
GPS_COM1.baud(460800); wait_ms(500); //without this wait -- the baud rate is not detected when using MODSERIAL
//GPS_COM1.baud(921600); wait_ms(500); //without this wait -- the baud rate is not detected when using MODSERIAL
};
void setupTriggers()
{
// camera1Int.mode(PullUp);
camera2Pin = 1;
//establish Trigger ISR
// camera1Int.rise(&camera1ISR);
};
/////////////////////////////////////////////////////////////////////
// mbed main to support the Waldo_FCS
/////////////////////////////////////////////////////////////////////
int main() {
//these are structures for the to GPS messages that must be parsed
OEM615BESTPOS posMsg; //BESTPOS structure in OEMV615.h that has matching time to a BESTVEL message
OEM615BESTPOS curPos; //BESTPOS structure in OEMV615.h
OEM615BESTVEL velMsg; //BESTVEL structure in OEMV615.h that has matching time to a BESTPOS message
OEM615BESTVEL curVel; //BESTVEL structure in OEMV615.h
//set up the GPS and mbed COM ports
setupCOM();
//set up the ADIS16488
setupADIS();
//setup Hotshoe
setupTriggers();
setUpMessages(); //set up the expected text message commands frm the PC
//set up the interrupt to catch the GPS receiver serial bytes as they are presented
GPS_COM1.attach(&readSerialByte, MODSERIAL::RxIrq);
timeFromPPS.start(); //start the time for measuring time from 1PPS events
toPC.printf("\n\n top of the main loop \n\n");
int totalBytesWritten = 0;
//while(PPSCounter < 100)
///////////////////////////////////////////////////////////////////////////
// top of the while loop
///////////////////////////////////////////////////////////////////////////
while(1)
{
//read the USB serial data from the PC to check for commands
//in the primary real-time portion, there are no bytes from the PC so this has no impact
readFromPC();
processPCmessages(fpNav, posMsg, velMsg);
//
////////////////////////////////////////////////////////////////////////////
//below is where we process the complete stored GPS message for the second
//The !IMUDataReady test prevents the IMU and GPS data from being written
//to disk on the same pass through thi loop
/////////////////////////////////////////////////////////////////////////////
if (!IMUDataReady && lookingForMessages && (timeFromPPS.read_us() > 20000)) //it takes less than 20msec to receive all messages
{
//toPC.printf(" num messages = %3d time = %5d \n", perSecMessageCounter, timeFromPPS.read_us());
//cycle through all the bytes stored this sec (after the 1PPS as set)
// perSecMessageCounter is incremented whenever we detect a new message headet 0xAA44121C sequence
for (int i=0; i<perSecMessageCounter; i++)
{
msgHeader[i] = (MESSAGEHEADER*)&msgBuffer[messageLocation[i]];
//toPC.printf("WMsg MESSAGEINFO %5d %5d \n",
// msgHeader[i]->messageID,
// messageLocation[i]);
//calculated CRC
unsigned long CRC1 = CalculateBlockCRC32(28+msgHeader[i]->messageLength, &msgBuffer[messageLocation[i]]);
unsigned long CRC2 = *((unsigned long*)&msgBuffer[messageLocation[i] + 28 + msgHeader[i]->messageLength]);
if (CRC1 != CRC2)
{
TotalBadCRCmatches++;
toPC.printf(" bad CRC match for messageID %3d total CRC errors = %4d \n",
msgHeader[i]->messageID, TotalBadCRCmatches);
continue;
}
//test for a message 42 (BESTPOS)
if (msgHeader[i]->messageID == 42)
{
curPos = *((OEM615BESTPOS*)&msgBuffer[messageLocation[i]]);
if (streamPos)
{
toPC.printf("WMsg BESTPOS %d %d %d %8.5lf %9.5lf %5.3lf %5.3f %5.3f %5.3f %5.3f %5.3f %5.3f %d %d %d %d %d\n",
curPos.msgHeader.GPSTime_msecs,
curPos.solStatus,
curPos.posType,
curPos.latitude,
curPos.longitude,
curPos.height,
curPos.undulation,
curPos.latitudeSTD,
curPos.longitudeSTD,
curPos.heightSTD,
curPos.diffAge,
curPos.solutionAge,
curPos.numSV,
curPos.numSolSV,
curPos.numGGL1,
curPos.extSolStatus,
curPos.sigMask);
}
}
//check for a message 99 (BESTVEL) -- and cast it into its message structure
else if (msgHeader[i]->messageID == 99)
{
curVel = *((OEM615BESTVEL*)&msgBuffer[messageLocation[i]]);
}
//the below test ensures that the positin and veocity are matched in time
//not sure the reason for the "250" below
if ((curVel.msgHeader.GPSTime_msecs+250)/1000 ==
(curPos.msgHeader.GPSTime_msecs+250)/1000)
{
// update position and velocity used for calculation
GPSTimemsecs = curPos.msgHeader.GPSTime_msecs;
GPSTime = (double)GPSTimemsecs/1000.0;
velMsg = curVel; //
posMsg = curPos;
/////////////////////////////////////////////////////////////////////////////////////////
//IMPORTANT: we reset the PPSTimeOffset when we have a matching position and velocity
PPSTimeOffset = 0;
/////////////////////////////////////////////////////////////////////////////////////////
}
} //end of per message loop
lookingForMessages = false;
if (recordData && (fpNav != NULL) && (byteCounter > 0))
{
wait_us(1000);
totalBytesWritten += fwrite(msgBuffer, 1, byteCounter, fpNav); // this writes out a complete set of messages for this sec
wait_us(1000);
}
} //end of the GPS message processing
//
//the IMU data record is read from the SPI in the ISR and the IMUDataReady is set true
//we write the IMU data here
if (IMUDataReady) //IMUDataReady is true if we have a recent IMU data record
{
//GPSTime (secs from midnight) is from the header of the position message
//PPSTimeOffset accounts for time becoming known ~20msec AFTER the 1PPS
imuRec.GPSTime = GPSTimemsecs + PPSTimeOffset*1000 + timeFromPPS.read_us()/1000.0;
wait_us(10);
spi.write((int) HIGH_REGISTER[0]); wait_us(10); // next read will return results from HIGH_REGITER[0]
for (int i=0; i<6; i++) //read the 6 rate and accel variables
{
wd.pt[1] = (unsigned short)spi.write((int) LOW_REGISTER[i]); wait_us(10) ;
if (i<5) // dont this on the last because this was pre-called
{ wd.pt[0] = (unsigned short)spi.write((int) HIGH_REGISTER[i+1]); wait_us(10); }
imuRec.dataWord[i] = wd.dataWord; //data word is a signed long
}
IMURecordCounter++;
//write the IMU data
if (recordData && (fpNav != NULL))
{
totalBytesWritten += fwrite(&imuRec, 1, sizeof(IMUREC), fpNav);
}
IMUClockCounter++;
IMUDataReady = false;
}
/*
if (messageDetected) //some GPS message header has been detected
{
toPC.printf(" msgTime = %4d \n", timeFromPPS.read_us());
messageDetected = false;
}
*/
if (camera1EventDetected) //we have detected a camera trigger event
{
camera2Pin=0;
wait(.25);
camera2Pin=1;
wait(.50);
camera2Pin=0;
camera1Time = GPSTime + PPSTimeOffset + timeFromPPS.read();
toPC.printf("WMsg TRIGGERTIME %5.3lf\n", camera1Time);
camera2Pin=1;
camera1EventDetected = false;
}
if (detectedGPS1PPS) //true if we are exactly at a 1PPS event detection
{
//toPC.printf(" PPSCounter=%4d byteCounter=%10d Msgs Received=%3d IMUClock=%4d bytesWritten=%8d\n",
// PPSCounter, savedByteCounter, savedPerSecMessageCounter, savedIMUClockCounter, totalBytesWritten);
detectedGPS1PPS = false;
}
}
fclose(fpNav);
toPC.printf(" normal termination \n");
}
