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

Dependencies:   mbed

Fork of GPS_Incremental by Dan Matthews

Files at this revision

API Documentation at this revision

Comitter:
jekain314
Date:
Tue Apr 02 15:22:37 2013 +0000
Parent:
5:46903325b61f
Child:
7:2e20e4cf53e6
Commit message:
JEK changes enabling proper recording of IMU/GPS datastreams to the SD-card

Changed in this revision

ADIS16488.h Show annotated file Show diff for this revision Revisions of this file
OEM615.h Show annotated file Show diff for this revision Revisions of this file
PCMessaging.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/ADIS16488.h	Fri Mar 29 20:52:54 2013 +0000
+++ b/ADIS16488.h	Tue Apr 02 15:22:37 2013 +0000
@@ -22,13 +22,12 @@
 struct IMUREC
 {
     unsigned long synch;
-    unsigned char msgID;
-    double GPSTime;
+    unsigned short msgID;
+    unsigned long GPSTime;
     long dataWord[6];
+    //  4 + 2 + 4 + 24 = 34
 } imuRec;
 
-
-
 void IMUDataReadyISR(void)
 {   
     IMUDataReady = true;
@@ -40,7 +39,6 @@
     ADIS_DR.mode(PullDown);
     ADIS_RST = 0;
     
-    printf("\nStart of ADIS test\n");
     //  set the IMU dataReady ISR
     ADIS_DR.rise(&IMUDataReadyISR);
     
@@ -71,7 +69,13 @@
     //change the page to 0 to get the data
     spi.write((int)0x8000);  //change to page 0
     
+    toPC.printf(" setting the default values\n");
+    
     //set the IMU synch and message ID
-    imuRec.synch = 0xAA44121C;  //same as the GPS synch words
+    imuRec.synch = 0x1C1244AA;  //same as the GPS synch words
+
     imuRec.msgID=111;  //IMU record ID
+    
+    toPC.printf(" finished setting the default values\n");
+
 }
--- a/OEM615.h	Fri Mar 29 20:52:54 2013 +0000
+++ b/OEM615.h	Tue Apr 02 15:22:37 2013 +0000
@@ -40,6 +40,26 @@
     unsigned long CRC;
 };
 
+/*  Solution Status descritpion from OEMV manual
+0   SOL_COMPUTED        Solution computed
+1   INSUFFICIENT_OBS    Insufficient observations
+2   NO_CONVERGENCE      No convergence
+3   SINGULARITY         Singularity at parameters matrix
+4   COV_TRACE           Covariance trace exceeds maximum (trace > 1000 m)
+5   TEST_DIST           Test distance exceeded (maximum of 3 rejections if distance >10 km)
+6   COLD_START          Not yet converged from cold start
+7   V_H_LIMIT           Height or velocity limits exceeded
+8   VARIANCE            Variance exceeds limits
+9   RESIDUALS           Residuals are too large
+10  DELTA_POS           Delta position is too large
+11  NEGATIVE_VAR        Negative variance
+12  Reserved
+13  INTEGRITY_WARNING   Large residuals make position unreliable
+18  PENDING             
+19  INVALID_FIX         The fixed position, entered using the FIX POSITION command, is not valid
+20  UNAUTHORIZED        Position type is unauthorized - HP or XP 
+*/
+
 #pragma pack(1)
 //structure for BESTPOS message 
 struct OEM615BESTPOS
@@ -72,6 +92,26 @@
     unsigned long CRC;
 };
 
+//GPS-specific pins
+DigitalOut GPS_Reset(p18);      //GPS RESET line
+InterruptIn PPSInt(p15);        // GPS 1PPS (timemark) from the OEM615
+InterruptIn IMUClock(p17);
+
+Timer timeFromPPS;
+unsigned long GPSTimemsecs = 0;
+double GPSTime = 0;
+int PPSTimeOffset = 0;
+
+//mbed tx/rx interface to the GPS COM1 port
+MODSERIAL GPS_COM1(p9,p10);  //this serial port communicates with the GPS receiver serial port (COM1)
+
+int test = 0;
+unsigned short messageCounter = 0;
+unsigned short savedMessageCounter = 0;
+const unsigned short maxGPSbytesPerSec = 1536;
+unsigned char msgBuffer[maxGPSbytesPerSec];  //array to contain one full second of GPS bytes
+const unsigned char maxGPSMessagesPerSec = 12;
+unsigned short messageLocation[maxGPSMessagesPerSec] = {0};  //stores the message location start within the message buffer
 
 //this code was taken from the Novatel Firmware document page 35
 #define CRC32_POLYNOMIAL 0xEDB88320L
@@ -113,18 +153,54 @@
     return( ulCRC );
 }
 
-//GPS-specific pins
-DigitalOut GPS_Reset(p18);      //GPS RESET line
-InterruptIn PPSInt(p15);        // GPS 1PPS (timemark) from the OEM615
-InterruptIn IMUClock(p17);
+
+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
+};
+
 
-Timer timeFromPPS;
-unsigned long GPSTimemsecs = 0;
-double GPSTime = 0;
-int PPSTimeOffset = 0;
+//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 % maxGPSbytesPerSec] = synch0;
 
-//mbed tx/rx interface to the GPS COM1 port
-MODSERIAL GPS_COM1(p9,p10);  //this serial port communicates with the GPS receiver serial port (COM1)
+    //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 % maxGPSMessagesPerSec] = 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) 
+
+};
 
 
 
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCMessaging.h	Tue Apr 02 15:22:37 2013 +0000
@@ -0,0 +1,293 @@
+//these are defines for the messages that are sent from the PC across the USB
+//these messages produce reactions on the mbed
+const unsigned char STATUS_MSG          =0;
+const unsigned char POSVEL_MSG          =1;
+const unsigned char  STARTDATA_MSG      =2;
+const unsigned char  STOPDATA_MSG       =3;
+const unsigned char  STARTSTREAM_MSG    =4;
+const unsigned char  STOPSTREAM_MSG     =5;
+const unsigned char  STARTLOGINFO_MSG   =6;
+const unsigned char  STOPLOGINFO_MSG    =7;
+
+const double  DEGREES_TO_RADIANS = acos(-1.0)/180.0;
+const double eccen          = 0.0818191908426;  //WGS84 earth eccentricity
+const double earthRadius    = 6378137;          //WGS84 earthRadius in meters
+
+char serBuf[128];
+int serBufChars=0;
+
+//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;
+bool recordData     =false;
+
+
+const unsigned char numMessages = 8;    //number of potential messages
+char msgList[numMessages][32];          //text array storing the command messages from the PC
+char minMessageSize = 10;               //minimum size of a text message
+unsigned char CR = 0x0d;                //ASCII Carriage Return
+unsigned char LF = 0x0a;                //ASCII Line Feed
+
+void setUpMessages(void)
+{ 
+    //set up the ASCII text records that are candidates to be passed from the PC
+    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
+    
+    toPC.printf(" finished setting up messages \n");
+}
+
+void readFromPC()
+{
+     //The received commands only 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();  //read char from the USB serial link to the PC
+        
+        //incoming messages will end witb a CR / LF -- disregard these chars
+        if (inChar == CR || inChar == LF) return;
+        
+        serBuf[serBufChars++] = inChar; //set this char in a char array
+        
+        //no need to continue if numChars are less than the shortest candidate message
+        if (serBufChars < minMessageSize) return;
+        
+        // Append end of string
+        //We always assume we have a complete message string and test for this below
+        serBuf[serBufChars] = '\0';
+        
+        bool validMessage = false;
+        
+        // Check for valid message -- there are numMessages possible messages
+        for (int m = 0; m < numMessages && !validMessage; m++) //check for all messages ... 
+        {
+            //toPC.printf(" \n\n found chars to test %3d %3d %s \n\n\n ", serBufChars, strlen(msgList[m]), serBuf );
+
+            //check the current partial message against ALL possible messages
+            //messages must match in both strength length and text
+            if (serBufChars == strlen(msgList[m]) && strncmp(serBuf, msgList[m], serBufChars) == 0 )
+            {
+            
+                //toPC.printf( "\n       found valid message \n\n");
+
+                validMessage = true;
+                serBufChars = 0; //reset the character count to reset for next message
+    
+                //set programmatic action flags based on the message
+                switch(m)
+                {
+                    case STATUS_MSG:
+                        sendStatus = true;  //send a status message back to PC
+                    break;
+                    case POSVEL_MSG:
+                        sendPosVel = true;  //send a posvel message back to PC
+                    break;
+                    case STARTDATA_MSG:  //start the data recording to the SD card
+                        recordData = true;
+                        sendRecData = true;
+                        break;
+                    case STOPDATA_MSG:   //stop the data recording to the SD card
+                        recordData = false;
+                        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;  
+                }  //end Switch statement
+                break;
+            } //end test for a valid message
+        }  //end message text loop
+    }  //end pc.readable
+};
+
+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
+    //latRateFac & lonRateFac multiplied by Vnorth or VEast to get latRate and lonRate
+    //see this document (page 32)    www.fas.org/spp/military/program/nav/basicnav.pdf
+
+    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;
+        
+    //divide Vnorth by latRateFac to get the latitude rate in deg per sec
+    latRateFac = (r_meridian + height)* DEGREES_TO_RADIANS;
+    
+    //divide VEast by lonRateFac to get the longitude rate in deg per sec
+    lonRateFac =  (r_normal + height) * cos(latitudeRad)* DEGREES_TO_RADIANS;
+}
+
+void sendPosVelMessageToPC(OEM615BESTPOS posMsg, OEM615BESTVEL velMsg)
+{
+            //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);
+            
+            double latRateFac;
+            double lonRateFac;
+                        
+            earthCoefficients(  posMsg.latitude*DEGREES_TO_RADIANS, 
+                                posMsg.longitude*DEGREES_TO_RADIANS, 
+                                posMsg.height, 
+                                latRateFac, lonRateFac);
+            
+            //commented calculations are for a spherical earth (Chris's original computation)
+            // 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;
+            
+            //toPC.printf(" elTime = %6.3f PPSimeOffset = %6.3f \n", elTime, PPSTimeOffset);
+            //toPC.printf(" latRateFac = %10.3f  lonRateFac = %10.3f \n", latRateFac, lonRateFac);
+            //toPC.printf(" latRateFac = %10.3f  lonRateFac = %10.3f \n", latMetersPerDeg, lonMetersPerDeg);
+
+            // 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 latPos = posMsg.latitude  + (nVel/latRateFac)*elTime;
+            double lonPos = posMsg.longitude + (eVel/lonRateFac)*elTime;            
+            double htPos  = posMsg.height    + velMsg.verticalSpeed/(60*1852)*elTime;
+            
+            toPC.printf("WMsg POSVEL %5.3lf %1d %s %8.5lf %9.5lf %4.3lf %4.3lf %4.3lf %4.3lf\n", 
+                         posTime, 
+                         posMsg.numSolSV,
+                         posMsg.solStatus,
+                         latPos,
+                         lonPos,
+                         htPos,
+                         nVel,
+                         eVel,
+                         velMsg.verticalSpeed
+                         );
+}
+
+void processPCmessages(FILE* &fpNav, OEM615BESTPOS posMsg, OEM615BESTVEL velMsg)
+{
+
+        //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
+            sendPosVelMessageToPC(posMsg, velMsg);
+        }
+        
+        //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';
+            //solStatus 
+            if (posMsg.solStatus == 0) //see description of solution status in OEMV615.h
+            {
+                solReady = 'Y';
+            }
+            toPC.printf("WMsg STATUS %5.3lf %c\n", 
+                         GPSTime, 
+                         solReady
+                         );
+        }
+        
+        //should just record ALL the data -- can pick 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");
+                    //toPC.printf("\n opened the SD card file recordData=%10d \n\n", fpNav);
+                }
+                if (fpNav != NULL)
+                {
+                    recChar = 'Y';
+                }
+                else
+                {
+                    toPC.printf(" Could not open the SD card \n\n");
+                }
+            }
+            else
+            {
+                if (fpNav != NULL)
+                {
+                    toPC.printf(" closing the SD card file \n\n");
+                    fclose(fpNav);
+                    recordData = false;
+                    fpNav = NULL;
+                }
+            }
+            toPC.printf("WMsg RECORDDATA %c\n", 
+                         recChar
+                         );
+        }
+        
+        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
+                         );
+        }
+        
+
+}
--- 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;
         }
     }