this version has all of Jim's fixes for reading the GPS and IMU data synchronously

Dependencies:   MODSERIAL SDFileSystem mbed SDShell CRC CommHandler FP LinkedList LogUtil

Revision:
29:dead10cce6e9
Parent:
27:94a6f0589993
Child:
30:96d133f3008e
--- a/main.cpp	Wed Nov 13 22:12:04 2013 +0000
+++ b/main.cpp	Thu Jan 09 14:09:05 2014 +0000
@@ -8,8 +8,11 @@
 #include "SDFileSystem.h"      //imported using the import utility    
 
 //general digital I/O specifications for this application
+
+//if we dont write to the card we dont need this ... 
 //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
@@ -21,23 +24,12 @@
 DigitalInOut fire(p29);     //connected to the tip of 2.5mm connector (T2i)
 DigitalInOut pre_fire(p30); //connected to the mid-connection for 2.5mm connector (T2i)
 
-
-
-/* Look at https://mbed.org/users/sam_grove/code/BufferedSerial/ */
-/* I wrote this and it works quite well. IRQ driven UART with software buffers for TX and RX */
-/* Same API as Serial with some enhancements */
-/* This will reduce the loop around main time. Right now the problem is that the delay */
-/* between events changes based on the UART speed */
-
 //USB serial data stream back to the PC
 Serial toPC(USBTX, USBRX);      //connect the GPS TX, RX to p9 and p10
 
 Timer timeFromStart;
-Timer timeFromPosVelMessageReceipt;
 
-/* should make all flags uint32_t for fastest access */
-/* encapsulate all this into a structure */
-/* or several based on what peripheral they belong to */
+
 
 bool detectedGPS1PPS = false;       //flag set in the ISR and reset after processing the 1PPS event
 int PPSCounter = 0;                 //counts the 1PPS occurrences
@@ -50,41 +42,16 @@
 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
 volatile int PPSTimeOffset = 0;
+int totalGPSBytes = 0;
 
-/* Ive done some of this. Look at: */
-/* https://mbed.org/users/sam_grove/code/OEM615/ */
-/* https://mbed.org/users/sam_grove/code/ADIS16488/ */
-/* a starting point that i'd done back during the hardware tester */
+bool writeIMUDataToPC = false;      //used in main loop to cause IMU data write to the PC
+bool writeGPSDataToPC = false;      //used in main loop to cause GPS data write to the PC
 
-//////////////////////////////////////////////////////////////////////
-// the below should become classes
-//////////////////////////////////////////////////////////////////////
 #include "OEM615.h"         //OEM615 GPS activities
 #include "ADIS16488.h"      //ADIS16488 activities
 #include "PCMessaging.h"    //PC messaging activities
 
-
-/* This should be called from a PC message handler when found. */
-
-// stuff to send the SD file to the PC
-#include "SDShell.h"
-void transferFile()
-{
-    SDShell emulate;    // create the object
-    emulate.init();     // init the params inside
-    GPS_Reset = 0;      // low power PCB mode
-    ADIS_RST = 0;       // same here
-    wait(0.01f);        // just make sure that the hardware has time to stop
-    fflush(stdout);     // and clear any TX reminants
-    toPC.printf("Entering Shell Emulator...\n");    // just for fluf
-    wait(0.1f);         // no reason for this either
-    emulate.shell(toPC, sd, "/sd"); // now the SDShell object will serve SD files via UNIX commands
-}
-
-/* Move into the GPS class */
-
 //ISR for detection of the GPS 1PPS
 void detect1PPSISR(void)
 {
@@ -109,14 +76,9 @@
 };
 
 
-
-/* Break up into GPS class and PC message class */
-/* GPS boot up messages should be checking for a response rather than waiting a predefined time */
-/* SD card stuff should also be a seperate class. Allow for dynamic directory and file awareness */
 ///////////////////////////////////////////////////////
 //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
@@ -134,25 +96,14 @@
     //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("WMsg start: %3d \n", 4-i); wait(1); }
+    //just wait some time to launch the GPS receiver
+    for (int i=0; i<5; i++) { toPC.printf("WMessage start countdown: %3d \n", 4-i); wait(1); }
 
-    sd_detect.mode(PullUp);
-    
-    if (sd_detect == 0)
-    {
-        mkdir("/sd/Data", 0777);
-    }
-    else
-    {
-        toPC.printf("WMsg 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
+    //this is the COM1 port from th GPS receiver 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);
    
@@ -169,15 +120,17 @@
     char ch2[] = "serialconfig COM1 115200 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
+    //Binary commands are shown below
+    //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";
+
+    //ASCII commands are shown below
+    char ch3[] = "log COM1 BESTPOSA ONTIME 1";   //messageID = 42 
+    char ch4[] = "log COM1 BESTVelA ONTIME 1";   //messageID = 99
+    char ch5[] = "log COM1 RANGEA ONTIME 1";     //messageID = 43
+    //char ch6[] = "log COM1 TIMEB ONTIME 1";      //messageID = 101
     
     //toPC.printf("WMsg set serial config \n");
     sendASCII(ch7, sizeof(ch7)); wait_ms(500);
@@ -214,130 +167,99 @@
 int main() 
 {
     
-    /* IMO this should all be ASCII (GPS data). Too much processing on the mbed side for messages that arent used */
-    /* the parsing and error checking + printf with floating point are EXPENSIVE CPU instructions */
-    
-    //these are structures for the to GPS messages that must be parsed
-    MESSAGEHEADER msgHdr;
-    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
-
-
-    /* Self explanitory */
+    toPC.printf("initiating the mbed app\n");
     
     fire.output();  //set the fire pin as outoput
     pre_fire.output();  //set the pre-fire pin as output
     
-    /* both should be open drain */
-    
     //fire.mode(OpenDrain);
     
-    /* not necessary if open drain outputs */
-    
     //set up for the first trigger
     fire = 1;
     pre_fire = 1;
     
-    /* for lower power modes of operation all this should be different classes and called when the PC requests it */
-    /* always on and idle is a waste of battery power. Could probabally add 30-50% life by leaving things off until needed */
-    
     //set up the GPS and mbed COM ports
     setupCOM(); 
-    
-    /* same as above */
-    
-    //set up the ADIS16488 
-    setupADIS();
+    toPC.printf("Completed setting up GPS \n");
 
-    setUpMessages();  //set up the expected text message commands from the PC 
-    
-    /* same as above */
-    
+    //set up the ADIS16488 IMU
+    //setupADIS();
+
     //initiate the interrupt to catch the GPS receiver serial bytes as they are presented
     GPS_COM1.attach(&readSerialByte, MODSERIAL::RxIrq);
     
-    /* same as above */
-    
     timeFromPPS.start();  //start the time for measuring time from 1PPS events
     timeFromStart.start();
     
-    //toPC.printf("\n\n top of the main loop \n\n");
-    
-    int totalBytesWritten = 0;
-    
-    /*establish the initial value for the CRC recursion after the header signature bytes
-    unsigned long CRC = 0;
-    CRC32Value(CRC, 0xAA);
-    CRC32Value(CRC, 0x44);
-    CRC32Value(CRC, 0x12);
-    CRC32Value(CRC, 0x1C);
-    //this results in a value of:   0x39b0f0e1
-    toPC.printf(" CRC after AA44121C header: %08x \n", CRC);
-    wait(20);
-    */
-    
-    //at the start we do not record the data
-    recordData = false;
-    sendRecData = false;     
-    
-    /* I'd get these off the stack and into a global structure */
-    /* If you did have a stack error condition (buffer overwrite) all this could be clobbered */
-    
     unsigned long cyclesPerSec = 0;  //main while() loop cycles per GPS sec
-    bool GPSdataWritten = false;
+
     bool finishTrigger = false;
     Timer triggerInterval;
     
-    //while(PPSCounter < 300)
-    
-    /* New command logic will keep this loop from ever exiting */
-    
     bool newMission = true;
     
     ///////////////////////////////////////////////////////////////////////////
     // top of the mission while loop
     ///////////////////////////////////////////////////////////////////////////
     while(newMission)
-    {        
-            
-        /* right idea. Build messages and parse */
-        
-        //read the USB serial data from the PC to check for commands
-        readFromPC();
-        
-        /* file should only be open when writing. If you crash and the file is open */
-        /* the data will be lost. Should be in a class that takes structures or strings to write to the file */
-        
-        //this will close the fpNav file on the SD card if the file is open 
-        //and the elapsed time from PosVel messages is > 60 secs
-        //this prevents loosing the fpNav file if the PC goes down
-        //   !!!! timeFromPosVelMessageReceipt !!! was never started
-        if (fpNav && (timeFromPosVelMessageReceipt.read() > 10) )
+    {         
+        if (message0Complete)
+        {
+            for (int i=0; i<GPSbyteCounter0; i++)   toPC.printf("%c", msgBuffer0[i]);
+            toPC.printf("\n");
+            message0Complete = false;
+        } 
+        else if (message1Complete)
+        {
+            for (int i=0; i<GPSbyteCounter1; i++)   toPC.printf("%c", msgBuffer1[i]);
+            toPC.printf("\n");
+            message1Complete = false;
+        }    
+        else if (message2Complete)
+        {
+            for (int i=0; i<GPSbyteCounter2; i++)   toPC.printf("%c", msgBuffer2[i]);
+            toPC.printf("\n");
+            message2Complete = false;
+        }         
+        /*
+        if (writeIMUDataToPC)
         {
-            sendRecData = true;
-            recordData  = false;
+            //write the IMU data to the PC
+            toPC.printf("IMURECORD ");  // 9 bytes header
+            for (int i=0; i<IMUrecArraySize; i++)
+            {
+                if (fillingPingWritingPong)
+                {
+                    toPC.printf("%d9 %d9 %d9 %d9 %d9 %d9 %d9", //70  bytes
+                    imuPong[i].GPSTime, 
+                    imuPong[i].dataWord[0],                    
+                    imuPong[i].dataWord[1],
+                    imuPong[i].dataWord[2],
+                    imuPong[i].dataWord[3],
+                    imuPong[i].dataWord[4],
+                    imuPong[i].dataWord[5]  );
+                }
+                else
+                {
+                   toPC.printf("%d9 %d9 %d9 %d9 %d9 %d9 %d9", 
+                    imuPing[i].GPSTime, 
+                    imuPing[i].dataWord[0],                    
+                    imuPing[i].dataWord[1],
+                    imuPing[i].dataWord[2],
+                    imuPing[i].dataWord[3],
+                    imuPing[i].dataWord[4],
+                    imuPing[i].dataWord[5]  );                
+                }
+            }
+            toPC.printf("/n");  //total of 10 * 70 + 9 = 709 bytes
+            writeIMUDataToPC = false;
         }
-                
-        /* Should be done when reading and building the message */
-        
-        // for any received PC message, take the appropriate action
-        processPCmessages(fpNav, posMsg, velMsg);
-        
-        /* file should always be closed until needed */
-        
-        //if we receive a "GETFILE" message from the PC -- close the fpNavFile and break from the while() loop
-        if (get_file_msg)  
-        {
-            if (fpNav != NULL) fclose(fpNav);
-            break;  //terminate the while loop when we receive this message from the PC
-        }
-        
-        /* wait looks unnecessary (and bad during runtime). During all tests with the camera the pre-fire is */
-        /* 250mS before the fire. Not sure if this changes the time til shutter open */
-        /* Look at the Timeout class */
-        
+        */
+            
+        //read the USB serial data from the PC to check for commands
+        //only message we expect will be thr trigger command
+        readFromPC();
+
         if(fireTrigger)  //comes from a PC request message
         {
             unsigned long triggerTime = GPSTimemsecs + PPSTimeOffset*1000.0 + timeFromPPS.read_us()/1000.0;
@@ -351,8 +273,6 @@
             triggerInterval.start();
         }
         
-        /* see above */
-        
         //the trigger requires a pulse -- the above portion lowers the signal and the below raises it
         //this has been tested at 50 msecs and it will not fire at that pulse duration
         if(finishTrigger && triggerInterval.read_ms() > 100)
@@ -363,123 +283,8 @@
             finishTrigger = false;  //completes the trigger firing pulse definition
         }
         
-        /* who clears this, PPS? */
-        
         cyclesPerSec++;
 
-        ////////////////////////////////////////////////////////////////////////////
-        //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 this loop  
-        /////////////////////////////////////////////////////////////////////////////        
-        
-        //there are three potential messages and all messages have a header
-        if (completeMessageAvailable && !IMUDataReady)
-        {
-            //must unpack header first to get the message length
-            msgHdr = *((MESSAGEHEADER*)&msgBuffer[messageLocation[savedMessageCounter-1]]);
-            
-            //these times are used to tag the IMU sample time. PPSTimeOffset increments by 1 exactly at the 1PPS event (in the 1PPS ISR)
-            //GPSTimemsecs increments by 1 for each new GPS measurement -- note that the below computations are actually
-            //done at the receipt of each GPS message. This is OK because each message has the same time in its header.
-            //Thus GPSTimemsecs increments by 1 here while GPSTimemsecs effectively decrements by 1.
-            //This handles IMU time tagging between the 1PPS event and the first receipt of a new GPS time.
-
-            //message header length is 28 -- right side is pointer to the receiver-computed CRC for this record 
-            //CRC is computed while reading in the GPS bytes
-            unsigned long msgCRC = *((unsigned long*)&msgBuffer[messageLocation[savedMessageCounter-1] + 28 + msgHdr.messageLength]);
-            
-            //toPC.printf("tmeFrom1PPS= %5d  ID= %3d Ln = %3d computedCRC= %08x msgCRC= %08x msgCntr = %3d CRCerr=%4d\n", 
-            //    timeFromPPS.read_us(), msgHdr.messageID, msgHdr.messageLength, computedCRC, msgCRC, savedMessageCounter, TotalBadCRCmatches);
-                
-            /* is this really necessary? Seems like keeping it in ascii and sending in ascii would make more sense */
-            
-            if ( msgCRC == computedCRC)  //computedCRC is performed as we read each bvyte
-            {
-                //if the CRC check is valid -- then get the time from the header
-                //we get three messages each sec -- does it matter that we do this three times?
-                GPSTimemsecs = msgHdr.GPSTime_msecs;  //time in GPS message header
-                
-                //the PPSTimeOffset accounts for the occurrence where we do not get any GPS messages over a sec -- but PPS is still operative
-                PPSTimeOffset = 0;                    //incremented by 1 in the PPS ISR
-            
-                //We need the pos and vel messages to pass back data to the PC -- error cases that can occur:
-                //  (1) missed 42 (POS)  -- use last good pos and extrapolate using last good vel
-                //  (2) missed 99 (VEL)  -- use the last good vel since likely not changed much
-                //  (3) missed both 42 and 99  -- must use last good position and extrapolae using last good velocity
-                //  GPS time used to time-tag the IMU data and to do the extrapolttion from last good position to send to PC
-                // in the position extrapolation, we will use the GPS time that is kept in the header of the POS msg (42)
-                // see the procedure:   sendPosVelMessageToPC()
-                     
-                if      (msgHdr.messageID == 42) //this is the position message (lat, lon, alt)
-                {
-                    //map the starting record byte index to the record structure
-                    curPos = *((OEM615BESTPOS*)&msgBuffer[messageLocation[savedMessageCounter-1]]);
-                    posMsg = curPos;
-                    
-                    if (streamPos)  // we no longer use this functionality
-                    {
-                            toPC.printf("BESTPOS %5d %1d %8.6lf %9.6lf %5.3lf %d %d\n",
-                                              curPos.msgHeader.GPSTime_msecs,  curPos.solStatus,
-                                              curPos.latitude, curPos.longitude, curPos.height,
-                                              curPos.numSV, curPos.numSolSV);
-                    }
-                    
-                } 
-                else if (msgHdr.messageID == 99)  //this is the velocity message
-                {
-                    curVel = *((OEM615BESTVEL*)&msgBuffer[ messageLocation[savedMessageCounter-1] ]);
-                    //toPC.printf("BESTVEL  vel: horizontalSpeed= %5.3f heading=%5.1f verticalSpeed=%4.2f \n", 
-                    //    curVel.horizontalSpeed,  curVel.heading,  curVel.verticalSpeed );
-                    velMsg = curVel;
-                }
-     
-                //below is set to true when we detect that we have received a complete GPS message
-                completeMessageAvailable = false;
-            }
-            else  // do this if we do not pass the CRC
-            {
-                toPC.printf("WMsg bad CRC match for messageID %3d total CRC errors = %4d \n",  
-                msgHdr.messageLength, TotalBadCRCmatches++);
-            }
-        }
-
-        
-        /* should move into a file management class for protection and error checking */
-        
-        //write the GPS data to the SD card
-        //NOTE:  this is valid only for a once-per-sec GPS message
-        //for this case, all messages come out well prior to 0.5 secs after the 1PPS
-        if (!IMUDataReady && !GPSdataWritten && timeFromPPS.read_us() > 500000 && recordData && (fpNav != NULL))
-        {
-                totalBytesWritten += fwrite(&msgBuffer, 1, byteCounter, fpNav);
-                GPSdataWritten = true;
-        }
-        
-        /* would have 2 arrays of structures and a pointer in the class than changes between the buffers. */
-        /* This way there is 1 write and management in 1 place */
-        
-        //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
-        {
-            //write the IMU data
-            if ( recordData && (fpNav != NULL) )
-            {   
-                //delTimeOfWrite = timeFromStart.read_us();
-                
-                if (fillingPingWritingPong) totalBytesWritten += fwrite(&imuPong, 1, IMUrecArraySize*sizeof(IMUREC), fpNav);
-                else                        totalBytesWritten += fwrite(&imuPing, 1, IMUrecArraySize*sizeof(IMUREC), fpNav);
-                    
-                //delTimeOfWrite = (unsigned long)((unsigned long)timeFromStart.read_us() - delTimeOfWrite);
-                //if (delTimeOfWrite > maxWriteTime) maxWriteTime = delTimeOfWrite;                
-            }
-            IMURecordCounter+=IMUrecArraySize;
-            IMUDataReady = false;
-        }
-        
-        /* should remove floating point if possible and send as milli-sec integers */
-        
         //this is a command from the PC to fire a trigger
         if (camera1EventDetected)  //we have detected a camera trigger event
         {
@@ -491,15 +296,13 @@
         
         if (detectedGPS1PPS)  //true if we are exactly at a 1PPS event detection
         {   
-            //toPC.printf("PPS=%4d stat=%1d bytes=%3d GPSMsgs=%2d  #write=%8d cycles=%6d\n", 
-            //                PPSCounter, posMsg.solStatus, savedByteCounter, savedPerSecMessageCounter, 
-            //                totalBytesWritten, cyclesPerSec );
+            toPC.printf("detected GPS 1PPS now  %5d %10d\n", PPSCounter, totalGPSBytes);
+            totalGPSBytes=0;
                             
             cyclesPerSec = 0;
-            //totalBytesWritten = 0;
-            GPSdataWritten = false;
-            //toPC.printf(" bytesWritten = %5d \n", totalBytesWritten);
             
+            messagePerSecCounter = 0;   //GPS message per second counter
+
             IMURecordCounter = 0;
             detectedGPS1PPS = false;
             
@@ -511,33 +314,5 @@
     ///////////////////////////////////////////
       
 
-     /* should already be closed by file management class */
-     
-     if (fpNav != NULL)
-     {
-        fclose(fpNav);  //insurance
-        toPC.printf("WMsg closeFPNav \n");
-     }
-     
-     /* accessable by SDShell class */
-     /* see: https://mbed.org/users/sam_grove/code/SDShell/ */
-     
-     toPC.printf("WMsg totalBytesWritten  %5d \n", totalBytesWritten);
-     wait_ms(100);
-     
-     /* just a state of the communication management class */
-     
-     //send the nav file to the PC
-     transferFile();
-     //rxMsg = txMsg = 0;  // just indicate that we're in here
-     // to exit this function the HOST (ie: computer or PC app) must send "exit" otherwise the mbed will act
-     // like a terminal and serve SD file data forever
-    
-     /* no longer needed */
-     
-     toPC.printf("WMsg normalTermination  \n");
-     wait_ms(100);
-     
-     NVIC_SystemReset();
     
 }
\ No newline at end of file