download gps_ubx.c
Language: C
License: GPL
Copyright: (C) 2003 Pascal Brisset, Antoine Drouin
LOC: 229
Project Info
paparazzi
Server: Savannah NonGNU
Type: cvs
...zzi\paparazzi3\sw\airborne\
   3dmg.c
   3dmg.h
   actuators.c
   actuators.h
   adc.h
   adc_generic.c
   adc_generic.h
   ahrs.c
   ahrs.h
   ahrs_new.c
   ahrs_new.h
   anemotaxis.c
   anemotaxis.h
   ap_downlink.h
   autopilot.h
   bomb.c
   bomb.h
   cam.c
   cam.h
   cam_roll.c
   cam_roll.h
   chemo_detect.c
   chemo_detect.h
   chemotaxis.c
   chemotaxis.h
   commands.c
   commands.h
   control_grz.c
   control_grz.h
   datalink.c
   datalink.h
   dc.c
   dc.h
   discsurvey.c
   discsurvey.h
   downlink.c
   downlink.h
   dpicco.c
   dpicco.h
   enose.c
   enose.h
   estimator.c
   estimator.h
   fbw_downlink.h
   frames.h
   fw_h_ctl.c
   fw_h_ctl.h
   fw_v_ctl.c
   fw_v_ctl.h
   gps.c
   gps.h
   gps_ubx.c
   gps_ubx.h
   gyro.c
   gyro.h
   i2c.c
   i2c.h
   imu.c
   imu.h
   imu_v3.c
   imu_v3.h
   infrared.c
   infrared.h
   inter_mcu.c
   inter_mcu.h
   latlong.c
   latlong.h
   led.h
   link_imu.c
   link_imu.h
   link_mcu.c
   link_mcu.h
   main.c
   main_antenna.c
   main_ap.c
   main_ap.h
   main_demo1.c
   main_demo2.c
   main_demo3.c
   main_demo4.c
   main_demo5.c
   main_demo6.c
   main_fbw.c
   main_fbw.h
   main_grz.c
   main_imu.c
   main_motor_bench.c
   modem.h
   nav.c
   nav.h
   nav_line.c
   nav_line.h
   nav_survey_rectangle.c
   nav_survey_rectangle.h
   paparazzi.h
   point.c
   point.h
   ppm.h
   pprz_transport.c
   pprz_transport.h
   print.h
   radio_control.c
   radio_control.h
   rc_settings.c
   rc_settings.h
   setup_actuators.c
   spi.c
   spi.h
   srf08.c
   srf08.h
   sys_time.c
   sys_time.h
   test_adcs.c
   traffic_info.c
   traffic_info.h
   uart.h
   usb_serial.h
   wavecard.c
   wavecard.h
   xbee.c
   xbee.h

/*
 * Paparazzi mcu0 $Id: gps_ubx.c,v 1.21 2007/08/29 14:09:22 hecto Exp $
 *  
 * Copyright (C) 2003  Pascal Brisset, Antoine Drouin
 *
 * This file is part of paparazzi.
 *
 * paparazzi is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * paparazzi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with paparazzi; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA. 
 *
 */

/** \file gps_ubx.c
 * \brief Parser for the UBX protocol (u-blox.com devices)
 */

#include <inttypes.h>
#include <string.h> 
#include <math.h>


#include "flight_plan.h"
#include "uart.h"
#include "gps.h"
#include "gps_ubx.h"
#include "nav.h"
#include "latlong.h"

#define UbxInitCheksum() { send_ck_a = send_ck_b = 0; }
#define UpdateChecksum(c) { send_ck_a += c; send_ck_b += send_ck_a; }
#define UbxTrailer() { GpsUartSend1(send_ck_a);  GpsUartSend1(send_ck_b); }

#define UbxSend1(c) { uint8_t i8=c; GpsUartSend1(i8); UpdateChecksum(i8); }
#define UbxSend2(c) { uint16_t i16=c; UbxSend1(i16&0xff); UbxSend1(i16 >> 8); }
#define UbxSend1ByAddr(x) { UbxSend1(*x); }
#define UbxSend2ByAddr(x) { UbxSend1(*x); UbxSend1(*(x+1)); }
#define UbxSend4ByAddr(x) { UbxSend1(*x); UbxSend1(*(x+1)); UbxSend1(*(x+2)); UbxSend1(*(x+3)); }

#define UbxHeader(nav_id, msg_id, len) { \
  GpsUartSend1(UBX_SYNC1); \
  GpsUartSend1(UBX_SYNC2); \
  UbxInitCheksum(); \
  UbxSend1(nav_id); \
  UbxSend1(msg_id); \
  UbxSend2(len); \
}


/** Includes macros generated from ubx.xml */ 
#include "ubx_protocol.h"


uint32_t gps_itow;
int32_t gps_alt;
uint16_t gps_gspeed;
int16_t gps_climb;
int16_t gps_course;
int32_t gps_utm_east, gps_utm_north;
uint8_t gps_utm_zone;
uint8_t gps_mode;
volatile bool_t gps_msg_received;
bool_t gps_pos_available;
uint8_t ubx_id, ubx_class;
int32_t gps_lat, gps_lon;

uint16_t gps_PDOP;
uint32_t gps_Pacc, gps_Sacc;
uint8_t gps_numSV;

#define UTM_HEM_NORTH 0
#define UTM_HEM_SOUTH 1

#define UBX_MAX_PAYLOAD 255

uint8_t ubx_msg_buf[UBX_MAX_PAYLOAD] __attribute__ ((aligned));

#define UNINIT        0
#define GOT_SYNC1     1
#define GOT_SYNC2     2
#define GOT_CLASS     3
#define GOT_ID        4
#define GOT_LEN1      5
#define GOT_LEN2      6
#define GOT_PAYLOAD   7
#define GOT_CHECKSUM1 8

static uint8_t  ubx_status;
static uint16_t ubx_len;
static uint8_t  ubx_msg_idx;
static uint8_t ck_a, ck_b;
uint8_t send_ck_a, send_ck_b;

uint8_t gps_status_config;

void gps_init( void ) {
  ubx_status = UNINIT;
#ifdef GPS_CONFIGURE
  gps_status_config = GPS_CONFIG_INIT;
#endif
}


#define UBX_PROTO_MASK  0x0001
#define NMEA_PROTO_MASK 0x0002
#define RTCM_PROTO_MASK 0x0004

#define NAV_DYN_AIRBORNE_1G 5
#define NAV_DYN_AIRBORNE_2G 6
#define NAV_DYN_AIRBORNE_4G 7

#ifdef GPS_CONFIGURE
/* GPS dynamic configuration */

#include "uart.h"

/* Configure the GPS baud rate using the current uart baud rate. Busy
   wait for the end of the transmit. Then, BEFORE waiting for the ACK,
   change the uart rate. */
void gps_configure_uart ( void ) {
  UbxSend_CFG_PRT(0x01, 0x0, 0x0, 0x000008D0, GPS_BAUD, UBX_PROTO_MASK, UBX_PROTO_MASK, 0x0, 0x0);  
  while (GpsUartRunning) ; /* FIXME */
  GpsUartInitParam( UART_BAUD(GPS_BAUD),  UART_8N1, UART_FIFO_8);
}

/* GPS configuration. Must be called on ack message reception while 
   gps_status_config < GPS_CONFIG_DONE */
void gps_configure ( void ) {
  if (ubx_class == UBX_ACK_ID) {
    if (ubx_id == UBX_ACK_ACK_ID) {
      gps_status_config++;
    }
  }
  switch (gps_status_config) {
  case 0:
    UbxSend_CFG_NAV(NAV_DYN_AIRBORNE_2G, 3, 16, 24, 20, 5, 0, 0x3C, 0x3C, 0x14, 0x03E8 ,0x0000, 0x0, 0x17, 0x00FA, 0x00FA, 0x0064, 0x012C, 0x000F, 0x00, 0x00);
    break;
  case 1:
    UbxSend_CFG_MSG(UBX_NAV_ID, UBX_NAV_POSUTM_ID, 0, 1, 0, 0);
    break;
  case 2:
    UbxSend_CFG_MSG(UBX_NAV_ID, UBX_NAV_VELNED_ID, 0, 1, 0, 0);
    break;
  case 3:
    UbxSend_CFG_MSG(UBX_NAV_ID, UBX_NAV_STATUS_ID, 0, 1, 0, 0);
    break;
  case 4:
    UbxSend_CFG_MSG(UBX_NAV_ID, UBX_NAV_SVINFO_ID, 0, 4, 0, 0);
    break;
  case 5:
    UbxSend_CFG_SBAS(0x00, 0x00, 0x00, 0x00, 0x00);
    break;
  case 6:
    UbxSend_CFG_RATE(0x00FA, 0x0001, 0x0000);   
    break;
  }
}
#endif /* GPS_CONFIGURE */

void ubxsend_cfg_rst(uint16_t bbr , uint8_t val) {
  UbxSend_CFG_RST(bbr, val, 0x00);
}


struct svinfo gps_svinfos[GPS_NB_CHANNELS];
uint8_t gps_nb_channels;

void parse_gps_msg( void ) {
  if (ubx_class == UBX_NAV_ID) {
    if (ubx_id == UBX_NAV_STATUS_ID) {
      gps_mode = UBX_NAV_STATUS_GPSfix(ubx_msg_buf);
#ifdef GPS_USE_LATLONG
  /* Computes from (lat, long) in the referenced UTM zone */
    } else if (ubx_id == UBX_NAV_POSLLH_ID) {
      gps_lat = UBX_NAV_POSLLH_LAT(ubx_msg_buf);
      gps_lon = UBX_NAV_POSLLH_LON(ubx_msg_buf);

      latlong_utm_of(RadOfDeg(gps_lat/1e7), RadOfDeg(gps_lon/1e7), nav_utm_zone0);
      
      gps_utm_east = latlong_utm_x * 100;
      gps_utm_north = latlong_utm_y * 100;
      gps_alt = UBX_NAV_POSLLH_HMSL(ubx_msg_buf) / 10;
      gps_utm_zone = nav_utm_zone0;
#else
    } else if (ubx_id == UBX_NAV_POSUTM_ID) {
      gps_utm_east = UBX_NAV_POSUTM_EAST(ubx_msg_buf);
      gps_utm_north = UBX_NAV_POSUTM_NORTH(ubx_msg_buf);
      uint8_t hem = UBX_NAV_POSUTM_HEM(ubx_msg_buf);
      if (hem == UTM_HEM_SOUTH)
	gps_utm_north -= 1000000000; /* Subtract false northing: -10000km */
      gps_alt = UBX_NAV_POSUTM_ALT(ubx_msg_buf);
      gps_utm_zone = UBX_NAV_POSUTM_ZONE(ubx_msg_buf);
#endif
    } else if (ubx_id == UBX_NAV_VELNED_ID) {
      gps_gspeed = UBX_NAV_VELNED_GSpeed(ubx_msg_buf);
      gps_climb = - UBX_NAV_VELNED_VEL_D(ubx_msg_buf);
      gps_course = UBX_NAV_VELNED_Heading(ubx_msg_buf) / 10000;
      gps_itow = UBX_NAV_VELNED_ITOW(ubx_msg_buf);
      
      gps_pos_available = TRUE; /* The 3 UBX messages are sent in one rafale */
    } else if (ubx_id == UBX_NAV_SOL_ID) {
      gps_PDOP = UBX_NAV_SOL_PDOP(ubx_msg_buf);
      gps_Pacc = UBX_NAV_SOL_Pacc(ubx_msg_buf);
      gps_Sacc = UBX_NAV_SOL_Sacc(ubx_msg_buf);
      gps_numSV = UBX_NAV_SOL_numSV(ubx_msg_buf);
    } else if (ubx_id == UBX_NAV_SVINFO_ID) {
      gps_nb_channels = UBX_NAV_SVINFO_NCH(ubx_msg_buf);
      uint8_t i;
      for(i = 0; i < Min(gps_nb_channels, GPS_NB_CHANNELS); i++) {
	gps_svinfos[i].svid = UBX_NAV_SVINFO_SVID(ubx_msg_buf, i);
	gps_svinfos[i].flags = UBX_NAV_SVINFO_Flags(ubx_msg_buf, i);
	gps_svinfos[i].qi = UBX_NAV_SVINFO_QI(ubx_msg_buf, i);
	gps_svinfos[i].cno = UBX_NAV_SVINFO_CNO(ubx_msg_buf, i);
	gps_svinfos[i].elev = UBX_NAV_SVINFO_Elev(ubx_msg_buf, i);
	gps_svinfos[i].azim = UBX_NAV_SVINFO_Azim(ubx_msg_buf, i);
      }
    }
  }
}


uint8_t gps_nb_ovrn;


void parse_ubx( uint8_t c ) {
  if (ubx_status < GOT_PAYLOAD) {
    ck_a += c;
    ck_b += ck_a;
  }
  switch (ubx_status) {
  case UNINIT:
    if (c == UBX_SYNC1)
      ubx_status++;
    break;
  case GOT_SYNC1:
    if (c != UBX_SYNC2)
      goto error;
    ck_a = 0;
    ck_b = 0;
    ubx_status++;
    break;
  case GOT_SYNC2:
    if (gps_msg_received) {
      /* Previous message has not yet been parsed: discard this one */
      gps_nb_ovrn++;
      goto error;
    }
    ubx_class = c;
    ubx_status++;
    break;
  case GOT_CLASS:
    ubx_id = c;
    ubx_status++;
    break;    
  case GOT_ID:
    ubx_len = c;
    ubx_status++;
    break;
  case GOT_LEN1:
    ubx_len |= (c<<8);
    if (ubx_len > UBX_MAX_PAYLOAD)
      goto error;
    ubx_msg_idx = 0;
    ubx_status++;
    break;
  case GOT_LEN2:
    ubx_msg_buf[ubx_msg_idx] = c;
    ubx_msg_idx++;
    if (ubx_msg_idx >= ubx_len) {
      ubx_status++;
    }
    break;
  case GOT_PAYLOAD:
    if (c != ck_a)
      goto error;
    ubx_status++;
    break;
  case GOT_CHECKSUM1:
    if (c != ck_b)
      goto error;
    gps_msg_received = TRUE;
    goto restart;
    break;
  }
  return;
 error:  
 restart:
  ubx_status = UNINIT;
  return;
}

About Koders | Resources | Downloads | Support | Black Duck | Submit Project | Terms of Service | DMCA | Privacy Policy | Site Map| Contact Us