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

Dependencies:   mbed

Fork of GPS_Incremental by Dan Matthews

Revision:
9:b45feb91ba38
Parent:
6:2a8486283198
--- a/OEM615.h	Wed Apr 17 13:50:21 2013 +0000
+++ b/OEM615.h	Fri Apr 19 16:21:27 2013 +0000
@@ -3,24 +3,26 @@
 //set up the GPS message header in a structure to enable easy reading -- see the OEM615 manual (Table 4, page 24)
 struct MESSAGEHEADER   
 {
-    char synchAA;  //1st synch word
-    char synch44;  //2nd synch word
-    char synch12;  //3rd synch word
-    unsigned char headerLength;  //always 28
-    unsigned short messageID;  //42 (BESTPOS) , 43 (RANGE) , or 99 (BESTVEL), 
-    char messageType;  //always = 0 for binary
-    unsigned char portAddress;  //0x20 for COM1
-    unsigned short messageLength; //not including header or CRC
-    unsigned short sequence;  //typically 0
-    unsigned char idleTime;  //Time the processor is idle, in the last second
-    unsigned char timeStatus; //Enum Indicating quality of the GPS reference time
-    unsigned short GPSweek;   //GPS reference week
-    unsigned long GPSTime_msecs; //from beginning of week
-    unsigned long receiverStatus; //32-bits representing the status of hardware and software
+    char synchAA;                   //1st synch word
+    char synch44;                   //2nd synch word
+    char synch12;                   //3rd synch word
+    unsigned char headerLength;     //always 28
+    unsigned short messageID;       //42  (0x2A  BESTPOS) , 43 (2B  RANGE) , or 99 (x63 BESTVEL), 
+    char messageType;               //always = 0 for binary
+    unsigned char portAddress;      //0x20 for COM1
+    // from spec:  The length in bytes of the body of the message, not including the header nor the CRC
+    unsigned short messageLength;   //not including header or CRC
+    unsigned short sequence;        //typically 0
+    unsigned char idleTime;         //Time the processor is idle, in the last second
+    unsigned char timeStatus;       //Enum Indicating quality of the GPS reference time
+    unsigned short GPSweek;         //GPS reference week
+    unsigned long GPSTime_msecs;    //from beginning of week
+    unsigned long receiverStatus;   //32-bits representing the status of hardware and software
     unsigned short reserved;
     unsigned short receiverSWversion;  //receiver software build number
+    //total length in bytes of this header is 28
 };
-MESSAGEHEADER *msgHeader[4];
+MESSAGEHEADER *msgHeader[6];
 
 #pragma pack(1)
 //structure for OEM615 BESTVEL log message  (page 314)
@@ -113,11 +115,23 @@
 const unsigned char maxGPSMessagesPerSec = 12;
 unsigned short messageLocation[maxGPSMessagesPerSec] = {0};  //stores the message location start within the message buffer
 
+unsigned short bytesFromMessageHdrDetect = 0;
+union SWAPBYTES { unsigned char b[2]; unsigned short w; };
+volatile SWAPBYTES messageLength;  //used to swap the bytes
+unsigned long computedCRC = 0;  //final resulting computed CRC for this message
+unsigned long incrementalCRC = 0;  //incrementally-formed CRC over message sequence
+unsigned short endByteForCRCcomputation = 0;
+bool completeMessageAvailable = false;
+
 //this code was taken from the Novatel Firmware document page 35
-#define CRC32_POLYNOMIAL 0xEDB88320L
+//#define CRC32_POLYNOMIAL 0xEDB88320L
 /* --------------------------------------------------------------------------
 Calculate a CRC value to be used by CRC calculation functions.
 -------------------------------------------------------------------------- */
+/*
+////////////////////////////////////////////
+//original code from the OEM615 manual
+////////////////////////////////////////////
 unsigned long CRC32Value(int i)
 {
     int j;
@@ -132,15 +146,53 @@
     }
     return ulCRC;
 } 
+*/
+
+#define CRC32_POLYNOMIAL 0xEDB88320L
+void CRC32Value(unsigned long &CRC, unsigned char c)
+{
+    /////////////////////////////////////////////////////////////////////////////////////
+    //CRC must be initialized as zero 
+    //c is a character from the sequence that is used to form the CRC
+    //this code is a modification of the code from the Novatel OEM615 specification
+    /////////////////////////////////////////////////////////////////////////////////////
+    unsigned long ulTemp1 = ( CRC >> 8 ) & 0x00FFFFFFL;
+    unsigned long ulCRC = ((int) CRC ^ c ) & 0xff ;
+    for (int  j = 8 ; j > 0; j-- )
+    {
+        if ( ulCRC & 1 )
+            ulCRC = ( ulCRC >> 1 ) ^ CRC32_POLYNOMIAL;
+        else
+            ulCRC >>= 1;
+    }
+    CRC = ulTemp1 ^ ulCRC;
+} 
 
 /* --------------------------------------------------------------------------
 Calculates the CRC-32 of a block of data all at once
-//the CRC is c from the complete message (header plus data) but excluding (of course) the CRC at the end
+//the CRC is from the complete message (header plus data) 
+//but excluding (of course) the CRC at the end
 -------------------------------------------------------------------------- */
 unsigned long CalculateBlockCRC32(
         unsigned long ulCount,    /* Number of bytes in the data block */
         unsigned char *ucBuffer ) /* Data block */
 {
+    //////////////////////////////////////////////////////////////////////
+    //the below code tests the CRC32Value procedure used in a markov form
+    //////////////////////////////////////////////////////////////////////
+    unsigned long CRC = 0;
+    for (int i = 0; i<ulCount; i++)  CRC32Value( CRC, *ucBuffer++ );
+    return  CRC;
+}
+
+/*
+unsigned long CalculateBlockCRC32(
+        unsigned long ulCount, 
+        unsigned char *ucBuffer )
+{
+////////////////////////////////////////////
+//original code from the OEM615 manual
+////////////////////////////////////////////
     unsigned long ulTemp1;
     unsigned long ulTemp2;
     unsigned long ulCRC = 0;
@@ -152,8 +204,7 @@
     }
     return( ulCRC );
 }
-
-
+*/
 void sendASCII(char* ASCI_message, int numChars)
 {
     /////////////////////////////////////////////////
@@ -178,24 +229,46 @@
 //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();
+    MODSERIAL *serial = q->serial;      //see example of MODSERIAL usage in cookbook
+    unsigned char synch0 = serial->getc();  //get the next byte
+    
+    //byteCounter is zeroed only at a 1PPA event in the 1PPS ISR
+    //all message bytes stored for a single GPS second 
     msgBuffer[byteCounter % maxGPSbytesPerSec] = synch0;
+    
+     //accumulate the CRC for this message
+     //incrementalCRC re-initialized after message header is is detected
+     CRC32Value( incrementalCRC, synch0); 
 
-    //we need to trap the GPS message header byte-string 0xAA44121C
+    //Trap the GPS message header byte-string per Novatel OEM615 spec: 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;  //
+    //shift last 4-byte value left 8 bits & push current-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;
-     }   
+        messageLocation[perSecMessageCounter % maxGPSMessagesPerSec] = byteCounter-3; //store the location of this message (1st of 4 synch word)
+        perSecMessageCounter++;  //counts messages this second
+        bytesFromMessageHdrDetect = 0;  //start byte counter for this message
+        incrementalCRC = 0x39b0f0e1;    //initializes the recursive CRC after the AA44121C header byte sequence 
+     }
+     else if (bytesFromMessageHdrDetect == 5) messageLength.b[0] = synch0;  //first byte of msg length
+     else if (bytesFromMessageHdrDetect == 6)   //second byte of message length
+     {
+        messageLength.b[1] = synch0; 
+        endByteForCRCcomputation = 24 + messageLength.w;  //use union to perform byte-swap from stored bytes
+     }
+     else if (bytesFromMessageHdrDetect == endByteForCRCcomputation)  //stop the CRC recursive computation
+        computedCRC = incrementalCRC;  //store the computed CRC for this message for use in main  
+     else if (bytesFromMessageHdrDetect == (endByteForCRCcomputation + 4) )  //detect the end of the message (end of its CRC)
+     {
+        savedMessageCounter = perSecMessageCounter;  //message counter can be corrupted before use in main
+        completeMessageAvailable = true;  //set flg for the main message processing
+     }
+         
      //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) 
-
+     bytesFromMessageHdrDetect++;  //counts the byes received after a message header
 };