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
Diff: OEM615.h
- Revision:
- 29:dead10cce6e9
- Parent:
- 28:fcea53fcc712
- Child:
- 30:96d133f3008e
--- a/OEM615.h Wed Nov 13 22:12:04 2013 +0000 +++ b/OEM615.h Thu Jan 09 14:09:05 2014 +0000 @@ -1,100 +1,5 @@ #include "crc.h" -#pragma pack(1) //this forces the structure to be packed on byte boundaries (with no byte filler) -//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 (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[6]; - -#pragma pack(1) -//structure for OEM615 BESTVEL log message (page 314) -struct OEM615BESTVEL -{ - MESSAGEHEADER msgHeader; - int solStatus; //solution status - //solutionStatusOEMStar solStatus; //solution status - int velType; //position or velocity type - //velTypeOEMStar posType; //position or velocity type - float latency; - float age; - double horizontalSpeed; //horizontal velocity vector magnitude (m/s) - double heading; //deg from North called TRK GND in specification - double verticalSpeed; //vertical velocity magnitude (m/s) - float reserved; - 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 -{ - MESSAGEHEADER msgHeader; - int solStatus; //solution status - //solutionStatusOEMStar solStatus; //solution status - int posType; //position or velocity type - //posTypeOEMStar posType; //position or velocity type - double latitude; //latitude - double longitude; //longitude - double height; //height above mean sea level - float undulation; //the realtionship between the geoid and the - //ellipsoid of the chosen datum (m) - char datumID[4]; //datum ID is actually an enum that is not implemented - float latitudeSTD; //latitude standard deviation - float longitudeSTD; //longitude standard deviation - float heightSTD; //height standard deviation - char baseStationID[4]; //base station ID - float diffAge; //differential age (s) - float solutionAge; //solution age (s) - unsigned char numSV; //number of satellite vehicles tracked - unsigned char numSolSV; //number of satellite vehicles used in solution - unsigned char numGGL1; //number of GPS plus Glonass L1 - unsigned char res1; - unsigned char res2; - unsigned char extSolStatus; //extended solution status - unsigned char res3; - unsigned char sigMask; //signals used mask - unsigned long CRC; -}; - //GPS-specific pins DigitalOut GPS_Reset(p18); //GPS RESET line InterruptIn PPSInt(p15); // GPS 1PPS (timemark) from the OEM615 @@ -106,21 +11,20 @@ //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 +bool loadingMessageBuffer = false; + +const unsigned short maxGPSbytesPerSec = 512; -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[maxGPSMessagesPerSec]; -bool completeMessageAvailable = false; +int messagePerSecCounter = 0; +unsigned char msgBuffer0[maxGPSbytesPerSec]; //array to contain one full second of GPS bytes +unsigned char msgBuffer1[maxGPSbytesPerSec]; //array to contain one full second of GPS bytes +unsigned char msgBuffer2[maxGPSbytesPerSec]; //array to contain one full second of GPS bytes +int GPSbyteCounter0 = 0; +int GPSbyteCounter1 = 0; +int GPSbyteCounter2 = 0; +bool message0Complete = false; +bool message1Complete = false; +bool message2Complete = false; void sendASCII(char* ASCI_message, int numChars) { @@ -149,48 +53,38 @@ 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); + totalGPSBytes++; - //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 current-read byte (synch0) into low-order byte - test = (test<<8) | synch0; - - //alternative 8-byte test (uses a long long 64bit word) - // AA44121C002A0020 //message 42 (BESTPOS) - // AA44121C002B0020 //message 43 (BESTVEL) - // AA44121C00990020 //message 99 (RANGE) - - if (test == 0xAA44121C) //test for the Receiver message header signature + //all OEM615 GPS ASCII messages begin with the unique character: "#" + //read til we get a "#" and then start storing the message + if (synch0 == '#') { - 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[perSecMessageCounter] = 24 + messageLength.w; //use union to perform byte-swap from stored bytes - } - else if (bytesFromMessageHdrDetect == endByteForCRCcomputation[perSecMessageCounter]) //stop the CRC recursive computation - computedCRC = incrementalCRC; //store the computed CRC for this message for use in main - else if (bytesFromMessageHdrDetect == (endByteForCRCcomputation[perSecMessageCounter] + 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 + if (messagePerSecCounter == 0) GPSbyteCounter0 = 0; + else if(messagePerSecCounter == 1) GPSbyteCounter1 = 0; + else if(messagePerSecCounter == 2) GPSbyteCounter2 = 0; + loadingMessageBuffer = true; + } + + if (messagePerSecCounter == 0) { msgBuffer0[GPSbyteCounter0 % maxGPSbytesPerSec] = synch0; GPSbyteCounter0++; } + else if(messagePerSecCounter == 1) { msgBuffer1[GPSbyteCounter1 % maxGPSbytesPerSec] = synch0; GPSbyteCounter1++; } + else if(messagePerSecCounter == 2) { msgBuffer2[GPSbyteCounter2 % maxGPSbytesPerSec] = synch0; GPSbyteCounter2++; } + + //stop storing the message when we get a LF + if (synch0 == 0x0a /* LF*/) //test for line feed + { + if (messagePerSecCounter == 0) message0Complete = true; + else if(messagePerSecCounter == 1) message1Complete = true; + else if(messagePerSecCounter == 2) message2Complete = true; + messagePerSecCounter++; //count the messages per second + } + + //how this can fail?? + // 1) get noisy # occurrences (unique starting character) + // 2) get noisy LF occurrences (unique ending character) + // 3) get noisy data packet values or extra values + // 4) we will also need to vet the data on the PC side + // 5) here, we should do minimal testing and just pass the data as is + };