Files @ c1b1dfc6c2f4
Branch filter:

Location: FeatherHAB/wsprhab/src/gps.c

Ethan Zonca
Modularize code a bit and switch to new GPS setup. Untested on hardware.
// TODO: Transition to using https://github.com/cuspaceflight/joey-m/blob/master/firmware/gps.c requesting UBX data

#include "stm32f0xx_hal.h"

#include "config.h"
#include "gpio.h"
#include "uart.h"
#include "gps.h"


typedef struct _gps_data
{
    int32_t hdop;
    int32_t sats_in_view;
    int32_t speed;
    int32_t heading;


    int32_t latitude;
    int32_t longitude;
    int32_t altitude;

    uint8_t hour;
    uint8_t minute;
    uint8_t second;

} gps_data_t;

gps_data_t position;

// Private methods
static void gps_ubx_checksum(uint8_t* data, uint8_t len, uint8_t* cka, uint8_t* ckb);
static uint8_t _gps_verify_checksum(uint8_t* data, uint8_t len);



void gps_init()
{
    // Initialize serial port
   // done in poweron uart_init();


//    // Disable GLONASS mode
//    uint8_t disable_glonass[20] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2};
//
//    gps_sendubx(disable_glonass, 20);
//
//    // Enable power saving
//    uint8_t enable_powersave[10] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92};
//    gps_sendubx(enable_powersave, 10);
//
//
//    // Set dynamic model 6 (<1g airborne platform)
//    uint8_t airborne_model[] = { 0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC };
//    gps_sendubx(airborne_model, sizeof(airborne_model)/sizeof(uint8_t));

}


void gps_update_position()
{
    // Request a NAV-POSLLH message from the GPS
    uint8_t request[8] = {0xB5, 0x62, 0x01, 0x02, 0x00, 0x00, 0x03,
        0x0A};
    //_gps_send_msg(request, 8);
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);

    uint8_t buf[36];
    HAL_UART_Receive(uart_gethandle(), buf, 36, 100);

    //for(uint8_t i = 0; i < 36; i++)
    //    buf[i] = _gps_get_byte();

//    // Verify the sync and header bits
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
//        led_set(LED_RED, 1);
//    if( buf[2] != 0x01 || buf[3] != 0x02 )
//        led_set(LED_RED, 1);

    // 4 bytes of longitude (1e-7)
    position.longitude = (int32_t)buf[10] | (int32_t)buf[11] << 8 |
        (int32_t)buf[12] << 16 | (int32_t)buf[13] << 24;

    // 4 bytes of latitude (1e-7)
    position.latitude = (int32_t)buf[14] | (int32_t)buf[15] << 8 |
        (int32_t)buf[16] << 16 | (int32_t)buf[17] << 24;

    // 4 bytes of altitude above MSL (mm)
    position.altitude = (int32_t)buf[22] | (int32_t)buf[23] << 8 |
        (int32_t)buf[24] << 16 | (int32_t)buf[25] << 24;

    //if( !_gps_verify_checksum(&buf[2], 32) ) led_set(LED_RED, 1);
}


void gps_update_time(uint8_t* hour, uint8_t* minute, uint8_t* second)
{
    // Send a NAV-TIMEUTC message to the receiver
    uint8_t request[8] = {0xB5, 0x62, 0x01, 0x21, 0x00, 0x00,
        0x22, 0x67};
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);

    // Get the message back from the GPS
    uint8_t buf[28];
    HAL_UART_Receive(uart_gethandle(), buf, 28, 100);

//    // Verify the sync and header bits
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
//        led_set(LED_RED, 1);
//    if( buf[2] != 0x01 || buf[3] != 0x21 )
//        led_set(LED_RED, 1);

    *hour = buf[22];
    *minute = buf[23];
    *second = buf[24];

//    if( !_gps_verify_checksum(&buf[2], 24) ) led_set(LED_RED, 1);
}

/**
 * Check the navigation status to determine the quality of the
 * fix currently held by the receiver with a NAV-STATUS message.
 */
void gps_check_lock(uint8_t* lock, uint8_t* sats)
{
    // Construct the request to the GPS
    uint8_t request[8] = {0xB5, 0x62, 0x01, 0x06, 0x00, 0x00,
        0x07, 0x16};
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);

    // Get the message back from the GPS
    uint8_t buf[60];
    HAL_UART_Receive(uart_gethandle(), buf, 60, 100);

    // Verify the sync and header bits
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
//        led_set(LED_RED, 1);
//    if( buf[2] != 0x01 || buf[3] != 0x06 )
//        led_set(LED_RED, 1);

    // Check 60 bytes minus SYNC and CHECKSUM (4 bytes)
//    if( !_gps_verify_checksum(&buf[2], 56) ) led_set(LED_RED, 1);

    // Return the value if GPSfixOK is set in 'flags'
    if( buf[17] & 0x01 )
        *lock = buf[16];
    else
        *lock = 0;

    *sats = buf[53];
}

/**
 * Verify that the uBlox 6 GPS receiver is set to the <1g airborne
 * navigaion mode.
 */
uint8_t gps_check_nav(void)
{
    uint8_t request[8] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00,
        0x2A, 0x84};
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);

    // Get the message back from the GPS
    uint8_t buf[44];
    HAL_UART_Receive(uart_gethandle(), buf, 44, 100);

//    // Verify sync and header bytes
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
//        led_set(LED_RED, 1);
//    if( buf[2] != 0x06 || buf[3] != 0x24 )
//        led_set(LED_RED, 1);

    // Check 40 bytes of message checksum
//    if( !_gps_verify_checksum(&buf[2], 40) ) led_set(LED_RED, 1);

    // Clock in and verify the ACK/NACK
    uint8_t ack[10];
    for(uint8_t i = 0; i < 10; i++)
        ack[i] = _gps_get_byte();

    // If we got a NACK, then return 0xFF
    if( ack[3] == 0x00 ) return 0xFF;

    // Return the navigation mode and let the caller analyse it
    return buf[8];
}

/**
 * Verify the checksum for the given data and length.
 */

static uint8_t _gps_verify_checksum(uint8_t* data, uint8_t len)
{
    uint8_t a, b;
    gps_ubx_checksum(data, len, &a, &b);
    if( a != *(data + len) || b != *(data + len + 1))
        return 0;
    else
        return 1;
}

// Calculate a UBX checksum using 8-bit Fletcher (RFC1145)
static void gps_ubx_checksum(uint8_t* data, uint8_t len, uint8_t* cka, uint8_t* ckb)
{
    *cka = 0;
    *ckb = 0;
    for( uint8_t i = 0; i < len; i++ )
    {
        *cka += *data;
        *ckb += *cka;
        data++;
    }
}


void gps_poweron(void)
{
    // NOTE: pchannel
    HAL_GPIO_WritePin(GPS_NOTEN, 0);
    uart_init();

    // Begin DMA reception
    //HAL_UART_Receive_DMA(uart_gethandle(), nmeaBuffer, NMEABUFFER_SIZE);
}


void gps_poweroff(void)
{
    // NOTE: pchannel
    uart_deinit();
    HAL_GPIO_WritePin(GPS_NOTEN, 1);
}

//
//uint8_t gps_hadfix = 0;
//uint8_t gps_hasfix()
//{
//	uint8_t hasFix = get_latitudeTrimmed()[0] != 0x00;
//	gps_hadfix = hasFix;
//	return hasFix;
//}



//void gps_sendubx(uint8_t* dat, uint8_t size)
//{
//    uint8_t sendctr;
//    for(sendctr = 0; sendctr < size; sendctr++)
//    {
//        HAL_UART_Transmit(huart1, dat[sendctr]);
//    }
//}

uint8_t gps_acquiring= 0;
uint32_t gps_lastfix_time;

void gps_acquirefix(void)
{
    gps_poweron();

    // Wait for fix
    gps_acquiring = 1;
}

uint8_t gps_getstate(void)
{
    if(gps_acquiring)
        return GPS_STATE_ACQUIRING;
    else if(gps_lastfix_time == 0)
        return GPS_STATE_NOFIX;
    else if(HAL_GetTick() - gps_lastfix_time < GPS_STALEFIX_MS)
        return GPS_STATE_FRESHFIX;
    else
        return GPS_STATE_STALEFIX;

}




// vim:softtabstop=4 shiftwidth=4 expandtab