Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The GPS continuously sends data as soon as it is plugged in. It sends data in the following data format:

Code Block
languagecpp
typedef struct _GPSData {

    long double latitude;  //8 Bytes

    long double longitude; //8 Bytes

    float time;     //4 Bytes

    float speed;

    int altitude;

    int heading;

    char satellites;    //1 Byte

    char positionFix;

} GPSData;

In order to properly configure this connection the following code is used:

Code Block
languagecpp
GPSData gpsData __attribute__((space(dma)));

/*

 *

 */

void __attribute__((__interrupt__, no_auto_psv)) _DMA2Interrupt(void){

    newGPSDataAvailable = 1;

    IFS1bits.DMA2IF = 0;// Clear the DMA0 Interrupt Flag

}

void init_DMA2(){

    IFS1bits.DMA2IF = 0;

    IEC1bits.DMA2IE = 1;

    DMA2CONbits.AMODE = 0b00; //Register Indirect Mode

    DMA2CONbits.DIR = 0; //Transfer from SPI to DSPRAM

    DMA2CONbits.MODE = 0b00; //Transfer continuously

    DMA2CONbits.SIZE = 1; //Transfer bytes (8 bits)

    DMA2STA = __builtin_dmaoffset(&gpsData); //Primary Transfer Buffer

    DMA2PAD = (volatile unsigned int) &SPI2BUF; //Peripheral Address

    DMA2CNT = sizeof(GPSData) - 1; //+1 for checksum //DMA Transfer Count Length

    DMA2REQ = 0b0100001; //IRQ code for SPI2

    DMA2CONbits.CHEN = 1; //Enable the channel

}

...

The data being sent to the PM chip from the AM chip is in the form of:

Code Block
languagecpp
typedef struct _AMData {

    WaypointWrapper waypoint;

    float pathGain;

    float orbitGain;

    float calibrationHeight;

    char command;

    char checksum;

} AMData;

Vice-versa, the data being sent to the AM chip from the PM chip is in the form of:

Code Block
languagecpp
typedef struct _PMData {

    float time;     //4 Bytes   -  hhmmss.ssss

    long double latitude;  //8 Bytes - ddd.mmmmmm

    long double longitude; //8 Bytes - ddd.mmmmmm

    float speed;    //KM/H

    float altitude;

    int sp_Altitude; // Meters

    int heading;  //Degrees

    int sp_Heading; //Degrees

    char satellites;    //1 Byte

    char positionFix;   //0 = No GPS, 1 = GPS fix, 2 = DGSP Fix

    char targetWaypoint;

    char batteryLevel;

 } PMData;

The initialization process is extremely similar for both chips (PM and AM). Each chip requires a DMA channel to read the incoming data, as well as to write the outgoing data. As a result, both the AM chip and the PM chip have the same setup with a few different variables names:

Code Block
languagecpp
void __attribute__((__interrupt__, no_auto_psv)) _DMA0Interrupt(void){

#if !PATH_MANAGER

    if (!transmitInitialized){

        transmitInitialized = 1;

        DMA1REQbits.FORCE = 1;

    while (DMA1REQbits.FORCE == 1);

    }

#endif

    newDataAvailable = 1;

    IFS0bits.DMA0IF = 0;// Clear the DMA0 Interrupt Flag

}

void __attribute__((__interrupt__, no_auto_psv)) _DMA1Interrupt(void){

    IFS0bits.DMA1IF = 0;// Clear the DMA0 Interrupt Flag

}

void init_DMA0(){

    IFS0bits.DMA0IF = 0;

    IEC0bits.DMA0IE = 1;

    IPC1bits.DMA0IP = 7; //Highest Priority

    DMACS0 = 0; //Clear any IO error flags

    DMA0CONbits.DIR = 0; //Transfer from SPI to DSPRAM

    DMA0CONbits.AMODE = 0b00; //With post increment mode

    DMA0CONbits.MODE = 0b00; //Transfer continuously

    DMA0CONbits.SIZE = 0; //Transfer words (16 bits)

#if PATH_MANAGER

    DMA0STA = __builtin_dmaoffset(&amData); //Primary Transfer Buffer

#else

    DMA0STA = __builtin_dmaoffset(&pmData); //Primary Transfer Buffer

#endif

    DMA0PAD = (volatile unsigned int) &SPI1BUF; //Peripheral Address

    DMA0CNT = PATH_MANAGER?(sizeof(AMData)/2 + sizeof(AMData) % 2 - 1):(sizeof(PMData)/2 + sizeof(PMData) % 2 - 1); //+1 for checksum //DMA Transfer Count Length

    DMA0REQ = 0x000A;//0b0100001; //IRQ code for SPI1

    DMA0CONbits.CHEN = 1; //Enable the channel

}

void init_DMA1(){

    IFS0bits.DMA1IF = 0;

    IEC0bits.DMA1IE = 1;

    IPC3bits.DMA1IP = 7;

    DMACS1 = 0; //Clear any IO error flags

    DMA1CONbits.DIR = 1; //Transfer from DSPRAM to SPI

    DMA1CONbits.AMODE = 0b00; //Without post increment mode

    DMA1CONbits.MODE = 0b00; //Transfer continuously, ping ponging between buffers

    DMA1CONbits.SIZE = 0; //Transfer words (16 bits)

#if PATH_MANAGER

    DMA1STA = __builtin_dmaoffset(&pmData); //Primary Transfer Buffer

#else

    DMA1STA = __builtin_dmaoffset(&amData); //Primary Transfer Buffer

#endif

    DMA1PAD = (volatile unsigned int) &SPI1BUF; //Peripheral Address

    DMA1CNT = PATH_MANAGER?(sizeof(PMData)/2 + sizeof(PMData) % 2 - 1):(sizeof(AMData)/2 + sizeof(AMData) % 2 - 1); //+1 for checksum //DMA Transfer Count Length

    DMA1REQ = 0x000A;//0b0100001; //IRQ code for SPI1

    DMA1CONbits.CHEN = 1; //Enable the channel

}

...

Also, in order to initialize transfer, the SPI master must send the first packet. This is evident in the DMA0 interrupt routine:

Code Block
languagecpp
#if !PATH\_MANAGER

    if (!transmitInitialized){

        transmitInitialized = 1;

        DMA1REQbits.FORCE = 1;

    while (DMA1REQbits.FORCE == 1);

    }

 #endif

...