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

OEM615.h

Committer:
jekain314
Date:
2013-11-13
Revision:
28:fcea53fcc712
Parent:
21:37551baf69c6
Child:
29:dead10cce6e9

File content as of revision 28:fcea53fcc712:

#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
InterruptIn IMUClock(p17);

Timer timeFromPPS;
unsigned long GPSTimemsecs = 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

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;

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
};


//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;      //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); 

    //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
    {
        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
};