2013-05-29 20:52:21 -03:00
|
|
|
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
2010-09-06 17:18:32 -03:00
|
|
|
|
2012-06-08 03:40:59 -03:00
|
|
|
|
|
|
|
|
2012-03-23 02:23:23 -03:00
|
|
|
#include <AP_Common.h>
|
|
|
|
#include <AP_Math.h>
|
2012-09-27 02:18:44 -03:00
|
|
|
#include <AP_HAL.h>
|
2013-08-13 23:52:30 -03:00
|
|
|
#include <AP_Notify.h>
|
2010-09-06 17:18:32 -03:00
|
|
|
#include "GPS.h"
|
2012-09-27 02:18:44 -03:00
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
|
|
|
|
#define GPS_DEBUGGING 0
|
|
|
|
|
|
|
|
#if GPS_DEBUGGING
|
|
|
|
# define Debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); hal.scheduler->delay(0); } while(0)
|
2012-01-27 23:25:47 -04:00
|
|
|
#else
|
2012-09-27 02:18:44 -03:00
|
|
|
# define Debug(fmt, args ...)
|
2012-01-27 23:25:47 -04:00
|
|
|
#endif
|
2010-09-06 17:18:32 -03:00
|
|
|
|
2013-02-19 20:32:15 -04:00
|
|
|
GPS::GPS(void) :
|
|
|
|
// ensure all the inherited fields are zeroed
|
2013-04-17 10:00:19 -03:00
|
|
|
time(0),
|
2013-09-16 08:20:36 -03:00
|
|
|
date(0),
|
|
|
|
latitude(0),
|
|
|
|
longitude(0),
|
|
|
|
altitude_cm(0),
|
|
|
|
ground_speed_cm(0),
|
|
|
|
ground_course_cd(0),
|
|
|
|
speed_3d_cm(0),
|
|
|
|
hdop(0),
|
2013-02-19 20:32:15 -04:00
|
|
|
num_sats(0),
|
|
|
|
new_data(false),
|
2013-03-25 04:24:14 -03:00
|
|
|
fix(FIX_NONE),
|
2013-02-19 20:32:15 -04:00
|
|
|
valid_read(false),
|
|
|
|
last_fix_time(0),
|
|
|
|
_have_raw_velocity(false),
|
2013-04-17 10:00:19 -03:00
|
|
|
_idleTimer(0),
|
2013-02-19 20:32:15 -04:00
|
|
|
_status(GPS::NO_FIX),
|
|
|
|
_last_ground_speed_cm(0),
|
|
|
|
_velocity_north(0),
|
|
|
|
_velocity_east(0),
|
2013-04-17 10:00:19 -03:00
|
|
|
_velocity_down(0)
|
2013-02-19 20:32:15 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-12-24 02:35:09 -04:00
|
|
|
void
|
|
|
|
GPS::update(void)
|
2010-10-17 17:13:53 -03:00
|
|
|
{
|
2012-08-17 03:19:44 -03:00
|
|
|
bool result;
|
|
|
|
uint32_t tnow;
|
2011-10-28 15:52:50 -03:00
|
|
|
|
|
|
|
// call the GPS driver to process incoming data
|
|
|
|
result = read();
|
|
|
|
|
2012-09-27 02:18:44 -03:00
|
|
|
tnow = hal.scheduler->millis();
|
2012-06-08 03:40:59 -03:00
|
|
|
|
2013-04-17 10:00:19 -03:00
|
|
|
// if we did not get a message, and the idle timer of 1.2 seconds has expired, re-init
|
2011-10-28 15:52:50 -03:00
|
|
|
if (!result) {
|
2013-04-17 10:00:19 -03:00
|
|
|
if ((tnow - _idleTimer) > 1200) {
|
2012-08-17 03:19:44 -03:00
|
|
|
Debug("gps read timeout %lu %lu", (unsigned long)tnow, (unsigned long)_idleTimer);
|
2011-10-28 15:52:50 -03:00
|
|
|
_status = NO_GPS;
|
|
|
|
|
2012-12-17 22:31:05 -04:00
|
|
|
init(_port, _nav_setting);
|
2011-10-28 15:52:50 -03:00
|
|
|
// reset the idle timer
|
2012-06-08 03:40:59 -03:00
|
|
|
_idleTimer = tnow;
|
2011-10-28 15:52:50 -03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// we got a message, update our status correspondingly
|
2013-03-25 04:24:14 -03:00
|
|
|
if (fix == FIX_3D) {
|
|
|
|
_status = GPS_OK_FIX_3D;
|
|
|
|
}else if (fix == FIX_2D) {
|
|
|
|
_status = GPS_OK_FIX_2D;
|
|
|
|
}else{
|
|
|
|
_status = NO_FIX;
|
|
|
|
}
|
2011-10-28 15:52:50 -03:00
|
|
|
|
|
|
|
valid_read = true;
|
|
|
|
new_data = true;
|
|
|
|
|
|
|
|
// reset the idle timer
|
2012-06-08 03:40:59 -03:00
|
|
|
_idleTimer = tnow;
|
2012-03-04 05:33:12 -04:00
|
|
|
|
2013-03-25 04:24:14 -03:00
|
|
|
if (_status >= GPS_OK_FIX_2D) {
|
2012-08-17 03:19:44 -03:00
|
|
|
last_fix_time = _idleTimer;
|
2013-07-10 01:01:53 -03:00
|
|
|
_last_ground_speed_cm = ground_speed_cm;
|
2012-08-17 03:19:44 -03:00
|
|
|
|
|
|
|
if (_have_raw_velocity) {
|
|
|
|
// the GPS is able to give us velocity numbers directly
|
2013-01-10 14:42:24 -04:00
|
|
|
_velocity_north = _vel_north * 0.01f;
|
|
|
|
_velocity_east = _vel_east * 0.01f;
|
|
|
|
_velocity_down = _vel_down * 0.01f;
|
2012-08-17 03:19:44 -03:00
|
|
|
} else {
|
2013-07-10 01:01:53 -03:00
|
|
|
float gps_heading = ToRad(ground_course_cd * 0.01f);
|
|
|
|
float gps_speed = ground_speed_cm * 0.01f;
|
2012-08-17 03:19:44 -03:00
|
|
|
float sin_heading, cos_heading;
|
|
|
|
|
2013-01-10 14:42:24 -04:00
|
|
|
cos_heading = cosf(gps_heading);
|
|
|
|
sin_heading = sinf(gps_heading);
|
2012-08-17 03:19:44 -03:00
|
|
|
|
|
|
|
_velocity_north = gps_speed * cos_heading;
|
|
|
|
_velocity_east = gps_speed * sin_heading;
|
2012-10-30 23:56:04 -03:00
|
|
|
|
|
|
|
// no good way to get descent rate
|
|
|
|
_velocity_down = 0;
|
2012-08-17 03:19:44 -03:00
|
|
|
}
|
|
|
|
}
|
2011-10-28 15:52:50 -03:00
|
|
|
}
|
2013-08-08 10:14:44 -03:00
|
|
|
|
|
|
|
// update notify with gps status
|
2013-08-13 23:52:30 -03:00
|
|
|
AP_Notify::flags.gps_status = _status;
|
2010-10-17 17:13:53 -03:00
|
|
|
}
|
2010-12-19 09:24:29 -04:00
|
|
|
|
2011-06-16 13:33:08 -03:00
|
|
|
void
|
2012-06-26 10:50:17 -03:00
|
|
|
GPS::setHIL(uint32_t _time, float _latitude, float _longitude, float _altitude,
|
2011-05-04 16:12:27 -03:00
|
|
|
float _ground_speed, float _ground_course, float _speed_3d, uint8_t _num_sats)
|
2011-02-19 14:33:42 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-12-24 02:35:09 -04:00
|
|
|
// XXX this is probably the wrong way to do it, too
|
2010-12-19 09:24:29 -04:00
|
|
|
void
|
2010-12-24 02:35:09 -04:00
|
|
|
GPS::_error(const char *msg)
|
2010-12-19 09:24:29 -04:00
|
|
|
{
|
2012-09-27 02:18:44 -03:00
|
|
|
hal.console->println(msg);
|
2010-12-19 09:24:29 -04:00
|
|
|
}
|
2012-06-15 02:53:14 -03:00
|
|
|
|
|
|
|
///
|
|
|
|
/// write a block of configuration data to a GPS
|
|
|
|
///
|
2012-09-27 02:18:44 -03:00
|
|
|
void GPS::_write_progstr_block(AP_HAL::UARTDriver *_fs, const prog_char *pstr, uint8_t size)
|
2012-06-15 02:53:14 -03:00
|
|
|
{
|
2012-08-17 03:19:44 -03:00
|
|
|
while (size--) {
|
|
|
|
_fs->write(pgm_read_byte(pstr++));
|
|
|
|
}
|
2012-06-15 02:53:14 -03:00
|
|
|
}
|
2012-10-18 02:18:12 -03:00
|
|
|
|
|
|
|
/*
|
|
|
|
a prog_char block queue, used to send out config commands to a GPS
|
|
|
|
in 16 byte chunks. This saves us having to have a 128 byte GPS send
|
|
|
|
buffer, while allowing us to avoid a long delay in sending GPS init
|
|
|
|
strings while waiting for the GPS auto detection to happen
|
|
|
|
*/
|
|
|
|
|
|
|
|
// maximum number of pending progstrings
|
|
|
|
#define PROGSTR_QUEUE_SIZE 3
|
|
|
|
|
|
|
|
struct progstr_queue {
|
|
|
|
const prog_char *pstr;
|
|
|
|
uint8_t ofs, size;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct {
|
2012-09-27 02:18:44 -03:00
|
|
|
AP_HAL::UARTDriver *fs;
|
2012-10-18 02:18:12 -03:00
|
|
|
uint8_t queue_size;
|
|
|
|
uint8_t idx, next_idx;
|
|
|
|
struct progstr_queue queue[PROGSTR_QUEUE_SIZE];
|
|
|
|
} progstr_state;
|
|
|
|
|
2012-09-27 02:18:44 -03:00
|
|
|
void GPS::_send_progstr(AP_HAL::UARTDriver *_fs, const prog_char *pstr, uint8_t size)
|
2012-10-18 02:18:12 -03:00
|
|
|
{
|
2012-09-27 02:18:44 -03:00
|
|
|
progstr_state.fs = _fs;
|
2012-10-18 02:18:12 -03:00
|
|
|
struct progstr_queue *q = &progstr_state.queue[progstr_state.next_idx];
|
|
|
|
q->pstr = pstr;
|
|
|
|
q->size = size;
|
|
|
|
q->ofs = 0;
|
|
|
|
progstr_state.next_idx++;
|
|
|
|
if (progstr_state.next_idx == PROGSTR_QUEUE_SIZE) {
|
|
|
|
progstr_state.next_idx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GPS::_update_progstr(void)
|
|
|
|
{
|
|
|
|
struct progstr_queue *q = &progstr_state.queue[progstr_state.idx];
|
|
|
|
// quick return if nothing to do
|
|
|
|
if (q->size == 0 || progstr_state.fs->tx_pending()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
uint8_t nbytes = q->size - q->ofs;
|
|
|
|
if (nbytes > 16) {
|
|
|
|
nbytes = 16;
|
|
|
|
}
|
2013-03-17 03:52:29 -03:00
|
|
|
//hal.console->printf_P(PSTR("writing %u bytes\n"), (unsigned)nbytes);
|
2012-10-18 02:18:12 -03:00
|
|
|
_write_progstr_block(progstr_state.fs, q->pstr+q->ofs, nbytes);
|
|
|
|
q->ofs += nbytes;
|
|
|
|
if (q->ofs == q->size) {
|
|
|
|
q->size = 0;
|
|
|
|
progstr_state.idx++;
|
|
|
|
if (progstr_state.idx == PROGSTR_QUEUE_SIZE) {
|
|
|
|
progstr_state.idx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-04-28 01:51:37 -03:00
|
|
|
|
|
|
|
int32_t GPS::_swapl(const void *bytes) const
|
|
|
|
{
|
|
|
|
const uint8_t *b = (const uint8_t *)bytes;
|
|
|
|
union {
|
|
|
|
int32_t v;
|
|
|
|
uint8_t b[4];
|
|
|
|
} u;
|
|
|
|
|
|
|
|
u.b[0] = b[3];
|
|
|
|
u.b[1] = b[2];
|
|
|
|
u.b[2] = b[1];
|
|
|
|
u.b[3] = b[0];
|
|
|
|
|
|
|
|
return(u.v);
|
|
|
|
}
|
|
|
|
|
|
|
|
int16_t GPS::_swapi(const void *bytes) const
|
|
|
|
{
|
|
|
|
const uint8_t *b = (const uint8_t *)bytes;
|
|
|
|
union {
|
|
|
|
int16_t v;
|
|
|
|
uint8_t b[2];
|
|
|
|
} u;
|
|
|
|
|
|
|
|
u.b[0] = b[1];
|
|
|
|
u.b[1] = b[0];
|
|
|
|
|
|
|
|
return(u.v);
|
|
|
|
}
|