JEK changes enabling proper recording of IMU/GPS datastrams - 02-APR-2013

Dependencies:   mbed

Fork of GPS_Incremental by Dan Matthews

Revision:
6:2a8486283198
Parent:
4:68268737ff89
Child:
7:2e20e4cf53e6
--- a/main.cpp	Fri Mar 29 20:52:54 2013 +0000
+++ b/main.cpp	Tue Apr 02 15:22:37 2013 +0000
@@ -1,227 +1,84 @@
 #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    
-//#include "rtos.h"
-#include "OEM615.h"
-
-#include "ADIS16488.h"
-#include <string>
-
-//these are defines for the messages that are sent from the PC across the USB
-//these messages produce reactions on the mbed
-#define STATUS_MSG 0
-#define POSVEL_MSG 1
-#define STARTDATA_MSG 2
-#define STOPDATA_MSG 3
-#define STARTSTREAM_MSG 4
-#define STOPSTREAM_MSG 5
-#define STARTLOGINFO_MSG 6
-#define STOPLOGINFO_MSG 7
-
-#define DEGREES_TO_RADIANS (3.14519/180.0)
 
 //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");
-//Serial debug(USBTX, USBRX); // tx, rx  USB communication to the PC for debug purposes
-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);  // i dont believe we use the second camera interrupt
+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
+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
-bool recordData = false;  //set to true when commanded from the PC
-int PPSCounter = 0;  //counts the 1PPS occurrences
-int byteCounter = 0; //byte counter -- where used??
+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
-int savedIMUClockCounter=0; 
-unsigned long IMUbytesWritten = 0;
-int savedByteCounter = 0;
-int savedPerSecMessageCounter=0;
-int IMUClockCounter = 0;
-bool camera1EventDetected = false;
-double camera1Time;
-char serBuf[128];
-int serBufChars=0;
+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
 
-//flags to control the PC command actions
-bool sendPosVel=false;
-bool sendStatus=false;
-bool sendRecData=false;
-bool streamPos=false;
-bool sendStreamPos=false;
-bool logMsgInfo=false;
-bool sendLogMsgInfo=false;
+//////////////////////////////////////////////////////////////////////
+// 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
+    timeFromPPS.reset();                    //reset the 1PPS timer upon 1PPS detection
     savedIMUClockCounter = IMUClockCounter; //number of IMU clocks received since last 1PPS
-    savedByteCounter = byteCounter;
-    savedPerSecMessageCounter = perSecMessageCounter;
-    IMUClockCounter = 0;  //counts number of IMU samples between 1PPS events
-    GPS_COM1.rxBufferFlush();  //flush the GPS serial buffer -- likely not needed but OK
-    byteCounter = 0;
-    perSecMessageCounter = 0;
+    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;  //reset in the main when 1PPS actions are complete
-    lookingForMessages = true; //means we should begin looking for new GPS messages
-    PPSCounter++;  //count number of 1PPS epochs
-    PPSTimeOffset++;   //counts the 1PPS events between occurrences when we have matching POS and VEL messages
-    ppsled = !ppsled;  //blink an LED at the 1PPS
+    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)
 {
-    //PPSTimeOffset keeps track of missed 
-    camera1Time = GPSTime + (double)PPSTimeOffset + timeFromPPS.read();
-    
+    //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
-    camera1EventDetected = true;  //reset to false in main after processing the image detection
 };
 
-void readFromPC()
-{
-
-    //better solution
-    //start a timer when we get a char from the PC and set a bool: detectingPCMessage = true
-    //keep reading bytes until elapsed time from the first byte is : 0.01 secs of numByes > 16
-    //the messages are from 10 to 16 bytes -- this will take from 10/921600 to 16/921600 secs at 921600 baud
-    //8*115200 = 921600
-    //this is about 2e-5  or 20usec.
-    //so we could wait 50usec from the first char reeived and be certain we had all the chars for a message.
-    //the steps are below .... 
-    //(1) convert this procedures to a ISR per byte
-    //(2) in the ISR, start the timer on the first byte received when !detectingPCMessage
-    //(3) set detectingPCMessage = true
-    //(4) in the main loop, test the timer for >50usec and parse the bytes to test fr a message
-    //(5) reset the timer to zero in the main loop after parsing the message
-    //(6) set detectingPCMessage = false;
-
-    //The received commands obnly occur at the initialization stage -- time is not that critical there.
-    //during the real-time action, we will never pass the followong if test ( no characters received)
-    if (toPC.readable()) //read a PC serial byte and test it for a command
-    {
-        // Read in next character
-        char inChar = toPC.getc();
-        serBuf[serBufChars++] = inChar;
-        
-        // Append end of string character
-        //why do this for every character we read?
-        //answer: we always assume we have a complete message and test for this below
-        serBuf[serBufChars] = '\0';
-        
-        // Need to parse message to determine behavior
-        // Need to clean this up 
-        //need to do this outside the read byte --- 
-        char msgList[8][32];
-        sprintf(msgList[STATUS_MSG], "WMsg STATUS");
-        sprintf(msgList[POSVEL_MSG], "WMsg POSVEL");
-        sprintf(msgList[STARTDATA_MSG], "WMsg RECORDDATA Y");
-        sprintf(msgList[STOPDATA_MSG], "WMsg RECORDDATA N");
-        sprintf(msgList[STARTSTREAM_MSG], "WMsg POSSTREAM Y");
-        sprintf(msgList[STOPSTREAM_MSG], "WMsg POSSTREAM N");
-        sprintf(msgList[STARTLOGINFO_MSG], "WMsg LOGINFO Y");
-        sprintf(msgList[STOPLOGINFO_MSG], "WMsg LOGINFO N");
-        //message length is from 10 to 16 chars
-        
-        // assume an invalid message which needs to be reset
-        bool validMessage = false;
-        bool resetMessage = true;
-        
-        // Check for valid message
-        for (int m = 0; m < 8 && !validMessage; m++) //check for all messages ... 
-        {
-            if (strncmp(serBuf, msgList[m], serBufChars) == 0)
-            {
-                validMessage = true;
-                //test that chars in the serial buffer is same as message length
-                if (serBufChars == strlen(msgList[m]))
-                {
-                    switch(m)
-                    {
-                        case STATUS_MSG:
-                            sendStatus = true;
-                        break;
-                        case POSVEL_MSG:
-                            sendPosVel = true;
-                        break;
-                        case STARTDATA_MSG:
-                        case STOPDATA_MSG:
-                            recordData = (m == STARTDATA_MSG);
-                            sendRecData = true;
-                        break;
-                        case STARTSTREAM_MSG:
-                        case STOPSTREAM_MSG:
-                            streamPos = (m == STARTSTREAM_MSG);
-                            sendStreamPos = true;
-                        break;
-                        case STARTLOGINFO_MSG:
-                        case STOPLOGINFO_MSG:
-                            logMsgInfo = (m == STARTLOGINFO_MSG);
-                            sendLogMsgInfo = true;
-                        break;
-                        
-                    }
-                }
-                // message is still in progress, do not reset
-                else
-                {
-                    resetMessage = false;
-                }
-            }
-        }
-        
-        // if message should be reset
-        if (resetMessage)
-        {
-            // reset serial buffer character count
-            serBufChars = 0;
-            // if invalid message and most recent character is 'W' (first message character),
-            // possible message collision
-            if ((!validMessage) && (inChar == 'W'))
-            {
-                // start a new message
-                serBuf[serBufChars++] = inChar;
-                serBuf[serBufChars] = '\0';
-            }
-            // Append end of string character
-            serBuf[serBufChars] = '\0';
-        }
-    }
-};
-
-void sendASCII(char* ASCI_message, int numChars)
-{
-    /////////////////////////////////////////////////
-    //send an ASCII command to the GPS receiver
-    /////////////////////////////////////////////////
-
-    //char ASCI_message[] = "unlogall COM1";
-    int as = numChars - 1;
-    unsigned char CR = 0x0d;  //ASCII Carriage Return
-    unsigned char LF = 0x0a;  //ASCII Line Feed
-    
-    //printf("%s", ch);
-    //printf("\n");
-
-    for (int i=0; i<as; i++) GPS_COM1.putc(ASCI_message[i]); 
-    GPS_COM1.putc(CR);   //carriage return at end
-    GPS_COM1.putc(LF);   //line feed at end
-};
-
-//FILE* fp = NULL;
+///////////////////////////////////////////////////////
+//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
@@ -242,18 +99,24 @@
     //just wait to launch the GPS receiver
     for (int i=0; i<5; i++) { toPC.printf(" to start: %3d \n", 4-i); wait(1); }
 
-    
-    mkdir("/sd/Data", 0777);
+    sd_detect.mode(PullUp);
     
-    /*
-    fp = fopen("/sd/Data/IMUGPS.bin", "wb");
-    if (fp == NULL)
+    if (sd_detect == 0)
+    {
+        mkdir("/sd/Data", 0777);
+    }
+    else
+    {
+        toPC.printf(" SD card not present \n");
+    }
+    
+    fpNav = fopen("/sd/Data/IMUGPS.bin", "wb");
+    if (fpNav == NULL)
     {
         toPC.printf(" cannot open the IMUGPS data file \n");
     }
     else
         toPC.printf(" opened the IMUGPS data file \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
@@ -284,7 +147,7 @@
     //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";
+    //char ch8[] = "FREQUENCYOUT enable 10000 1000000";
     
     toPC.printf("set serial config \n");
     sendASCII(ch7, sizeof(ch7)); wait_ms(500);
@@ -301,8 +164,8 @@
     //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);
+    //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");
@@ -323,68 +186,16 @@
     
 };
 
-int test = 0;
-unsigned short messageCounter = 0;
-unsigned short savedMessageCounter = 0;
-unsigned char msgBuffer[1536];  //array to contain one full second of GPS bytes
-unsigned short messageLocation[6] = {0};  //stores the message location start within the message buffer
-
-//see the mbed COOKBOOK for MODSERIAL
-//MODSERIAL is an easy to use library that extends Serial to add fully buffered input and output.
-void readSerialByte(MODSERIAL_IRQ_INFO *q)
-{ 
-    MODSERIAL *serial = q->serial;
-    unsigned char synch0 = serial->getc();
-    msgBuffer[byteCounter] = synch0;
-
-    //we need to trap the GPS message header byte-string 0xAA44121C
-    //generate a 4-byte sliding-window sequence from the input bytes
-    //shift last 4-byte value left 8 bits & push recently read byte (synch0) into low-order byte
-    test = (test<<8) | synch0;  //
-   
-    if (test == 0xAA44121C) //test for the Receiver message header signature
-    {
-        messageLocation[perSecMessageCounter] = byteCounter-3; //store the location of this message (with 4 synch words)
-        perSecMessageCounter++;
-        messageDetected = true;
-     }   
-     //byteCounter reset to zero in main after the 1PPS is detected -- its NOT reset in the 1PPS ISR
-     byteCounter++;     //total per-sec byte counter (reset to zero in main when 1PPS detected) 
-
-};
-
-void earthCoefficients(double latitudeRad, double longitudeRad, double height, double &latRateFac, double &lonRateFac)
-{
-    //compute the lat and lon factors for use in the interpolation of the lat and lon between 1 sec epochs
-    //see this document (page 32)    www.fas.org/spp/military/program/nav/basicnav.pdf
-    double eccen = 0.0818191908426; //WGS84 earth eccentricity
-    double earthRadius = 6378137;  //WGS84 earthRadius in meters
-    double eccenSinLat = eccen * sin(latitudeRad); 
-    double temp1 = 1.0 - eccenSinLat*eccenSinLat;
-    double temp2 = sqrt(temp1);
-    double r_meridian = earthRadius * ( 1.0 - eccen*eccen)/ (temp1 * temp2);
-    double r_normal   = earthRadius / temp2;
+/////////////////////////////////////////////////////////////////////
+//  mbed main to support the Waldo_FCS
+/////////////////////////////////////////////////////////////////////
+int main() {
     
-    //multiply latRateFac times V-north to get the latitude rate in radians [er sec
-    latRateFac = 1.0 / (r_meridian + height);
-    
-    //multiply lonRatFac by VEast to get the longitude rate in radians per sec
-    lonRateFac = 1.0  / ( (r_normal + height) * cos(latitudeRad) );
-}
-
-int main() {
-
-    //FILE *fpIMU = NULL;
-    //FILE *fpGPS = NULL;
-    FILE *fpNav = NULL;
-    
-    OEM615BESTPOS posMsg;   //BESTPOS structure in OEMV615.h
+    //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
+    OEM615BESTVEL velMsg;   //BESTVEL structure in OEMV615.h that has matching time to a BESTPOS message
     OEM615BESTVEL curVel;   //BESTVEL structure in OEMV615.h
-    
-    int msgLen;
-    int msgEnd;
 
     //set up the GPS and mbed COM ports
     setupCOM(); 
@@ -394,166 +205,30 @@
     
     //setup Hotshoe
     setupTriggers();
-    
-    //attempt to use the mbed RTOS library
-    //Thread thread(writeThread);
-    
-    //this doesnt show up on the PC Rich Text Box because we dont start the init til after this occurs
-    toPC.printf("completed setting up COM ports \n");
+
+    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
-
-    while(PPSCounter < 100)
+    
+    toPC.printf("\n\n top of the main loop \n\n");
+    
+    int totalBytesWritten = 0;
+    
+    //while(PPSCounter < 100)
     ///////////////////////////////////////////////////////////////////////////
     // top of the while loop
     ///////////////////////////////////////////////////////////////////////////
-    //while(1)
+    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();
-
-        //we should put the below stuff into the readPC() procedure.
-        //only do these actions in response to a command so no need for the tests w/o an inoput byte from the PC
-        //perform the activities as a response to the commands
-        if (sendPosVel)  //true if we want to return a position solution
-        {
-            sendPosVel=false; //set to true if a POSVEL is requested from the PC
-            char solReady = 'N';
-            if (posMsg.solStatus == 0)  //how is this set??
-            {
-                solReady = 'Y';
-            }
-            
-            //north and east velocity from the horizontal speed and heading
-            //velMsg may not be the "current" message --- but is the one also associated with a position message
-            double nVel = velMsg.horizontalSpeed*cos(velMsg.heading*DEGREES_TO_RADIANS);
-            double eVel = velMsg.horizontalSpeed*sin(velMsg.heading*DEGREES_TO_RADIANS);
-            
-            // For the 1 second deltas with which we are dealing
-            // This calculation should be close enough for now
-            // Approximately 1 nautical mile / minute latitude, 60 minutes/degree, 1852 meters/nautical mile
-            double latMetersPerDeg = 60.0*1852.0;
-            // longitude separation is approximately equal to latitude separation * cosine of latitude
-            double lonMetersPerDeg = latMetersPerDeg*cos(posMsg.latitude*DEGREES_TO_RADIANS);
-
-            // Elapsed time since last known GPS position
-            //PPSTimeOffset is a result of possibly missing a prior GPS position message
-            // timeFromPPS.read() is always the time from the moset recent 1PPS
-            double elTime = (double)PPSTimeOffset + timeFromPPS.read();
-            
-            // Position time -- GPSTime is the time of the last valid GPS position message
-            double posTime = GPSTime + elTime;
+        processPCmessages(fpNav, posMsg, velMsg);
 
-            // Estimated position based on previous position and velocity
-            // posMsg is the last time when the BESTVEL and BESTPOS messages had identical times
-            double latPos = posMsg.latitude + (nVel/latMetersPerDeg)*elTime;
-            double lonPos = posMsg.longitude + (eVel/lonMetersPerDeg)*elTime;
-            double htPos = posMsg.height + velMsg.verticalSpeed/(60*1852)*elTime;
-            toPC.printf("WMsg POSVEL %5.3lf %d %c %8.5lf %9.5lf %4.3lf %4.3lf %4.3lf %4.3lf\n", 
-                         posTime, 
-                         posMsg.numSolSV,
-                         solReady,
-                         latPos,
-                         lonPos,
-                         htPos,
-                         nVel,
-                         eVel,
-                         velMsg.verticalSpeed
-                         );
-        }
-        
-        //all this does is assess the GPS convergence -- really available in the above
-        if (sendStatus)  //send the status message to the PC
-        {
-            sendStatus=false;
-            char solReady = 'N';
-            if (posMsg.solStatus == 0)
-            {
-                solReady = 'Y';
-            }
-            toPC.printf("WMsg STATUS %5.3lf %c\n", 
-                         GPSTime, 
-                         solReady
-                         );
-        }
-        
-        //should just record ALL the data -- can pck over it in the post-processing
-        if (sendRecData)  //begin to (or stop) record the serial data
-        {
-            sendRecData=false;
-            char recChar = 'N';
-            if (recordData)
-            {
-                if ((fpNav == NULL))
-                {
-                    fpNav = fopen("/sd/Data/NAV.bin", "wb");
-                }
-                if (fpNav != NULL)
-                {
-                    recChar = 'Y';
-                }
-                //recChar = 'Y';
-            }
-            else
-            {
-                if (fpNav != NULL)
-                {
-                    fclose(fpNav);
-                    fpNav = NULL;
-                }
-                /*
-                if (fpIMU != NULL)
-                {
-                    fclose(fpIMU);
-                    fpIMU = NULL;
-                }
-                if (fpGPS != NULL)
-                {
-                    fclose(fpGPS);
-                    fpGPS = NULL;
-                }
-                */
-            }
-            toPC.printf("WMsg RECORDDATA %c\n", 
-                         recChar
-                         );
-        }
-        
-        //this is called everytime through the loop -- wasteful
-        //recordDataled = recordData;
-        
-        if (sendStreamPos)  //stream the position data to the PC
-        {
-            sendStreamPos=false;
-            char streamChar = 'N';
-            if (streamPos)
-            {
-                streamChar = 'Y';
-            }
-            toPC.printf("WMsg POSSTREAM %c\n", 
-                         streamChar
-                         );
-        }
-        
-        //not sure this is ever used ..
-        if (sendLogMsgInfo)  //send log info to the PC
-        {
-            sendLogMsgInfo=false;
-            char logChar = 'N';
-            if (logMsgInfo)
-            {
-                logChar = 'Y';
-            }
-            toPC.printf("WMsg LOGINFO %c\n", 
-                         logChar
-                         );
-        }
-        
-
+//
         ////////////////////////////////////////////////////////////////////////////
         //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 
@@ -561,16 +236,29 @@
         /////////////////////////////////////////////////////////////////////////////
         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());
+            //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]);
+                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)
                 {
@@ -621,41 +309,53 @@
                     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
         {
-            imuRec.GPSTime = GPSTimemsecs + timeFromPPS.read_us()/1000000.0;
-            spi.write((int) HIGH_REGISTER[0]); // next read will return results from HIGH_REGITER[0]
+            //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]) ; 
+                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]); }
+                {   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 && (fpIMU != NULL))
             if (recordData && (fpNav != NULL))
-            {
-                IMUbytesWritten += fwrite(imuRec.dataWord, sizeof(IMUREC), 1, fpNav);
+            {   
+                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
         {
@@ -665,13 +365,9 @@
         
         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, IMUbytesWritten);
-            if (recordData && (fpNav != NULL) && (byteCounter > 0))
-            {
-                // we know that we are not reading a GPS message at exactly the 1PPS occurrence
-                fwrite(msgBuffer, byteCounter, 1, fpNav);  // this writes out a complete set of messages for ths sec
-            }
+            //toPC.printf(" PPSCounter=%4d byteCounter=%10d Msgs Received=%3d IMUClock=%4d bytesWritten=%8d\n", 
+            //                PPSCounter, savedByteCounter, savedPerSecMessageCounter, savedIMUClockCounter, totalBytesWritten);
+
             detectedGPS1PPS = false;
         }
     }