2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
5 * @addtogroup GPSModule GPS Module
6 * @brief Process GPS information (UBX binary format)
10 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015-2016.
11 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
12 * @brief GPS module, handles GPS and UBX stream
13 * @see The GNU Public License (GPL) Version 3
15 *****************************************************************************/
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "openpilot.h"
34 #include "pios_math.h"
35 #include <pios_helpers.h>
36 #include <pios_delay.h>
38 #if defined(PIOS_INCLUDE_GPS_UBX_PARSER)
44 #if !defined(PIOS_GPS_MINIMAL)
45 #include <auxmagsupport.h>
46 static bool useMag
= false;
47 #endif /* !defined(PIOS_GPS_MINIMAL) */
49 // this is set and used by this low level ubx code
50 // it is also reset by the ubx configuration code (UBX6 vs. UBX7) in ubx_autoconfig.c
51 GPSPositionSensorSensorTypeOptions ubxSensorType
= GPSPOSITIONSENSOR_SENSORTYPE_UNKNOWN
;
53 static bool usePvt
= false;
54 static uint32_t lastPvtTime
= 0;
60 void (*handler
)(struct UBXPacket
*, GPSPositionSensorData
*GpsPosition
);
61 } ubx_message_handler
;
63 // parsing functions, roughly ordered by reception rate (higher rate messages on top)
64 static void parse_ubx_nav_posllh(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
65 static void parse_ubx_nav_velned(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
66 static void parse_ubx_nav_sol(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
67 static void parse_ubx_nav_dop(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
68 #if !defined(PIOS_GPS_MINIMAL)
69 static void parse_ubx_nav_pvt(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
70 static void parse_ubx_nav_timeutc(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
71 static void parse_ubx_nav_svinfo(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
72 static void parse_ubx_op_sys(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
73 static void parse_ubx_op_mag(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
74 static void parse_ubx_ack_ack(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
75 static void parse_ubx_ack_nak(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
76 static void parse_ubx_mon_ver(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
);
77 #endif /* !defined(PIOS_GPS_MINIMAL) */
79 const ubx_message_handler ubx_handler_table
[] = {
80 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_POSLLH
, .handler
= &parse_ubx_nav_posllh
},
81 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_VELNED
, .handler
= &parse_ubx_nav_velned
},
82 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_SOL
, .handler
= &parse_ubx_nav_sol
},
83 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_DOP
, .handler
= &parse_ubx_nav_dop
},
84 #if !defined(PIOS_GPS_MINIMAL)
85 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_PVT
, .handler
= &parse_ubx_nav_pvt
},
86 { .msgClass
= UBX_CLASS_OP_CUST
, .msgID
= UBX_ID_OP_MAG
, .handler
= &parse_ubx_op_mag
},
87 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_SVINFO
, .handler
= &parse_ubx_nav_svinfo
},
88 { .msgClass
= UBX_CLASS_NAV
, .msgID
= UBX_ID_NAV_TIMEUTC
, .handler
= &parse_ubx_nav_timeutc
},
90 { .msgClass
= UBX_CLASS_OP_CUST
, .msgID
= UBX_ID_OP_SYS
, .handler
= &parse_ubx_op_sys
},
91 { .msgClass
= UBX_CLASS_ACK
, .msgID
= UBX_ID_ACK_ACK
, .handler
= &parse_ubx_ack_ack
},
92 { .msgClass
= UBX_CLASS_ACK
, .msgID
= UBX_ID_ACK_NAK
, .handler
= &parse_ubx_ack_nak
},
94 { .msgClass
= UBX_CLASS_MON
, .msgID
= UBX_ID_MON_VER
, .handler
= &parse_ubx_mon_ver
},
95 #endif /* !defined(PIOS_GPS_MINIMAL) */
97 #define UBX_HANDLER_TABLE_SIZE NELEMENTS(ubx_handler_table)
99 // detected hw version
100 int32_t ubxHwVersion
= -1;
102 // Last received Ack/Nak
103 struct UBX_ACK_ACK ubxLastAck
;
104 struct UBX_ACK_NAK ubxLastNak
;
106 // If a PVT sentence is received in the last UBX_PVT_TIMEOUT (ms) timeframe it disables VELNED/POSLLH/SOL/TIMEUTC
107 #define UBX_PVT_TIMEOUT (1000)
109 // parse incoming character stream for messages in UBX binary format
110 int parse_ubx_stream(uint8_t *rx
, uint16_t len
, char *gps_rx_buffer
, GPSPositionSensorData
*GpsData
, struct GPS_RX_STATS
*gpsRxStats
)
124 enum restart_states
{
128 static uint16_t rx_count
= 0;
129 static enum proto_states proto_state
= START
;
130 struct UBXPacket
*ubx
= (struct UBXPacket
*)gps_rx_buffer
;
131 int ret
= PARSER_INCOMPLETE
; // message not (yet) complete
133 uint16_t restart_index
= 0;
134 enum restart_states restart_state
;
137 // switch continue is the normal condition and comes back to here for another byte
138 // switch break is the error state that branches to the end and restarts the scan at the byte after the first sync byte
141 switch (proto_state
) {
142 case START
: // detect protocol
143 if (c
== UBX_SYNC1
) { // first UBX sync char found
144 proto_state
= UBX_SY2
;
145 // restart here, at byte after SYNC1, if we fail to parse
150 if (c
== UBX_SYNC2
) { // second UBX sync char found
151 proto_state
= UBX_CLASS
;
153 restart_state
= RESTART_NO_ERROR
;
158 ubx
->header
.class = c
;
159 proto_state
= UBX_ID
;
163 proto_state
= UBX_LEN1
;
167 proto_state
= UBX_LEN2
;
170 ubx
->header
.len
+= (c
<< 8);
171 if (ubx
->header
.len
> sizeof(UBXPayload
)) {
172 gpsRxStats
->gpsRxOverflow
++;
173 #if defined(PIOS_GPS_MINIMAL)
174 restart_state
= RESTART_NO_ERROR
;
176 restart_state
= RESTART_WITH_ERROR
;
180 if (ubx
->header
.len
== 0) {
181 proto_state
= UBX_CHK1
;
183 proto_state
= UBX_PAYLOAD
;
189 if (rx_count
< ubx
->header
.len
) {
190 ubx
->payload
.payload
[rx_count
] = c
;
191 if (++rx_count
== ubx
->header
.len
) {
192 proto_state
= UBX_CHK1
;
197 ubx
->header
.ck_a
= c
;
198 proto_state
= UBX_CHK2
;
201 ubx
->header
.ck_b
= c
;
202 // OP GPSV9 sends data with bad checksums this appears to happen because it drops data
203 // this has been proven by running it without autoconfig and testing:
204 // data coming from OPV9 "GPS+MCU" port the checksum errors happen roughly every 5 to 30 seconds
205 // same data coming from OPV9 "GPS Only" port the checksums are always good
206 // this also occasionally causes parse_ubx_message() to issue alarms because not all the messages were received
207 // see OP GPSV9 comment in parse_ubx_message() for further information
208 if (checksum_ubx_message(ubx
)) {
209 gpsRxStats
->gpsRxReceived
++;
211 // overwrite PARSER_INCOMPLETE with PARSER_COMPLETE
212 // but don't overwrite PARSER_ERROR with PARSER_COMPLETE
213 // pass PARSER_ERROR to caller if it happens even once
214 // only pass PARSER_COMPLETE back to caller if we parsed a full set of GPS data
215 // that allows the caller to know if we are parsing GPS data
216 // or just other packets for some reason (mis-configuration)
217 if (parse_ubx_message(ubx
, GpsData
) == GPSPOSITIONSENSOR_OBJID
218 && ret
== PARSER_INCOMPLETE
) {
219 ret
= PARSER_COMPLETE
;
222 gpsRxStats
->gpsRxChkSumError
++;
223 restart_state
= RESTART_WITH_ERROR
;
231 // this simple restart doesn't work across calls
232 // but it does work within a single call
233 // and it does the expected thing across calls
234 // if restarting due to error detected in 2nd call to this function (on split packet)
235 // then we just restart at index 0, which is mid-packet, not the second byte
236 if (restart_state
== RESTART_WITH_ERROR
) {
237 ret
= PARSER_ERROR
; // inform caller that we found at least one error (along with 0 or more good packets)
239 rx
+= restart_index
; // restart parsing just past the most recent SYNC1
240 len
-= restart_index
;
248 // Keep track of various GPS messages needed to make up a single UAVO update
249 // time-of-week timestamp is used to correlate matching messages
250 #define POSLLH_RECEIVED (1 << 0)
251 #define STATUS_RECEIVED (1 << 1)
252 #define DOP_RECEIVED (1 << 2)
253 #define VELNED_RECEIVED (1 << 3)
254 #define SOL_RECEIVED (1 << 4)
255 #define ALL_RECEIVED (SOL_RECEIVED | VELNED_RECEIVED | DOP_RECEIVED | POSLLH_RECEIVED)
256 #define NONE_RECEIVED 0
258 static struct msgtracker
{
259 uint32_t currentTOW
; // TOW of the message set currently in progress
260 uint8_t msg_received
; // keep track of received message types
263 // Check if a message belongs to the current data set and register it as 'received'
264 bool check_msgtracker(uint32_t tow
, uint8_t msg_flag
)
266 if (tow
> msgtracker
.currentTOW
? true // start of a new message set
267 : (msgtracker
.currentTOW
- tow
> 6 * 24 * 3600 * 1000)) { // 6 days, TOW wrap around occured
268 msgtracker
.currentTOW
= tow
;
269 msgtracker
.msg_received
= NONE_RECEIVED
;
270 } else if (tow
< msgtracker
.currentTOW
) { // message outdated (don't process)
274 msgtracker
.msg_received
|= msg_flag
; // register reception of this msg type
278 bool checksum_ubx_message(struct UBXPacket
*ubx
)
283 ck_a
= ubx
->header
.class;
286 ck_a
+= ubx
->header
.id
;
289 ck_a
+= ubx
->header
.len
& 0xff;
292 ck_a
+= ubx
->header
.len
>> 8;
295 for (i
= 0; i
< ubx
->header
.len
; i
++) {
296 ck_a
+= ubx
->payload
.payload
[i
];
300 if (ubx
->header
.ck_a
== ck_a
&&
301 ubx
->header
.ck_b
== ck_b
) {
308 static void parse_ubx_nav_posllh(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
)
313 struct UBX_NAV_POSLLH
*posllh
= &ubx
->payload
.nav_posllh
;
315 if (check_msgtracker(posllh
->iTOW
, POSLLH_RECEIVED
)) {
316 if (GpsPosition
->Status
!= GPSPOSITIONSENSOR_STATUS_NOFIX
) {
317 GpsPosition
->Altitude
= (float)posllh
->hMSL
* 0.001f
;
318 GpsPosition
->GeoidSeparation
= (float)(posllh
->height
- posllh
->hMSL
) * 0.001f
;
319 GpsPosition
->Latitude
= posllh
->lat
;
320 GpsPosition
->Longitude
= posllh
->lon
;
325 static void parse_ubx_nav_sol(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
)
330 struct UBX_NAV_SOL
*sol
= &ubx
->payload
.nav_sol
;
331 if (check_msgtracker(sol
->iTOW
, SOL_RECEIVED
)) {
332 GpsPosition
->Satellites
= sol
->numSV
;
334 if (sol
->flags
& STATUS_FLAGS_GPSFIX_OK
) {
335 switch (sol
->gpsFix
) {
336 case STATUS_GPSFIX_2DFIX
:
337 GpsPosition
->Status
= GPSPOSITIONSENSOR_STATUS_FIX2D
;
339 case STATUS_GPSFIX_3DFIX
:
340 GpsPosition
->Status
= GPSPOSITIONSENSOR_STATUS_FIX3D
;
342 default: GpsPosition
->Status
= GPSPOSITIONSENSOR_STATUS_NOFIX
;
344 } else { // fix is not valid so we make sure to treat is as NOFIX
345 GpsPosition
->Status
= GPSPOSITIONSENSOR_STATUS_NOFIX
;
350 static void parse_ubx_nav_dop(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
)
352 struct UBX_NAV_DOP
*dop
= &ubx
->payload
.nav_dop
;
354 if (check_msgtracker(dop
->iTOW
, DOP_RECEIVED
)) {
355 GpsPosition
->HDOP
= (float)dop
->hDOP
* 0.01f
;
356 GpsPosition
->VDOP
= (float)dop
->vDOP
* 0.01f
;
357 GpsPosition
->PDOP
= (float)dop
->pDOP
* 0.01f
;
361 static void parse_ubx_nav_velned(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
)
366 GPSVelocitySensorData GpsVelocity
;
367 struct UBX_NAV_VELNED
*velned
= &ubx
->payload
.nav_velned
;
368 if (check_msgtracker(velned
->iTOW
, VELNED_RECEIVED
)) {
369 if (GpsPosition
->Status
!= GPSPOSITIONSENSOR_STATUS_NOFIX
) {
370 GpsVelocity
.North
= (float)velned
->velN
/ 100.0f
;
371 GpsVelocity
.East
= (float)velned
->velE
/ 100.0f
;
372 GpsVelocity
.Down
= (float)velned
->velD
/ 100.0f
;
373 GPSVelocitySensorSet(&GpsVelocity
);
374 GpsPosition
->Groundspeed
= (float)velned
->gSpeed
* 0.01f
;
375 GpsPosition
->Heading
= (float)velned
->heading
* 1.0e-5f
;
380 #if !defined(PIOS_GPS_MINIMAL)
381 static void parse_ubx_nav_pvt(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
)
383 lastPvtTime
= PIOS_DELAY_GetuS();
385 GPSVelocitySensorData GpsVelocity
;
386 struct UBX_NAV_PVT
*pvt
= &ubx
->payload
.nav_pvt
;
387 check_msgtracker(pvt
->iTOW
, (ALL_RECEIVED
));
389 GpsVelocity
.North
= (float)pvt
->velN
* 0.001f
;
390 GpsVelocity
.East
= (float)pvt
->velE
* 0.001f
;
391 GpsVelocity
.Down
= (float)pvt
->velD
* 0.001f
;
392 GPSVelocitySensorSet(&GpsVelocity
);
394 GpsPosition
->Groundspeed
= (float)pvt
->gSpeed
* 0.001f
;
395 GpsPosition
->Heading
= (float)pvt
->heading
* 1.0e-5f
;
396 GpsPosition
->Altitude
= (float)pvt
->hMSL
* 0.001f
;
397 GpsPosition
->GeoidSeparation
= (float)(pvt
->height
- pvt
->hMSL
) * 0.001f
;
398 GpsPosition
->Latitude
= pvt
->lat
;
399 GpsPosition
->Longitude
= pvt
->lon
;
400 GpsPosition
->Satellites
= pvt
->numSV
;
401 GpsPosition
->PDOP
= pvt
->pDOP
* 0.01f
;
402 if (pvt
->flags
& PVT_FLAGS_GNSSFIX_OK
) {
403 GpsPosition
->Status
= pvt
->fixType
== PVT_FIX_TYPE_3D
?
404 GPSPOSITIONSENSOR_STATUS_FIX3D
: GPSPOSITIONSENSOR_STATUS_FIX2D
;
406 GpsPosition
->Status
= GPSPOSITIONSENSOR_STATUS_NOFIX
;
409 if (pvt
->valid
& PVT_VALID_VALIDTIME
) {
410 // Time is valid, set GpsTime
413 GpsTime
.Year
= pvt
->year
;
414 GpsTime
.Month
= pvt
->month
;
415 GpsTime
.Day
= pvt
->day
;
416 GpsTime
.Hour
= pvt
->hour
;
417 GpsTime
.Minute
= pvt
->min
;
418 GpsTime
.Second
= pvt
->sec
;
420 GPSTimeSet(&GpsTime
);
424 static void parse_ubx_nav_timeutc(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
430 struct UBX_NAV_TIMEUTC
*timeutc
= &ubx
->payload
.nav_timeutc
;
431 // Test if time is valid
432 if ((timeutc
->valid
& TIMEUTC_VALIDTOW
) && (timeutc
->valid
& TIMEUTC_VALIDWKN
)) {
433 // Time is valid, set GpsTime
436 GpsTime
.Year
= timeutc
->year
;
437 GpsTime
.Month
= timeutc
->month
;
438 GpsTime
.Day
= timeutc
->day
;
439 GpsTime
.Hour
= timeutc
->hour
;
440 GpsTime
.Minute
= timeutc
->min
;
441 GpsTime
.Second
= timeutc
->sec
;
442 GpsTime
.Millisecond
= (int16_t)(timeutc
->nano
/ 1000000);
443 GPSTimeSet(&GpsTime
);
445 // Time is not valid, nothing to do
450 static void parse_ubx_nav_svinfo(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
453 GPSSatellitesData svdata
;
454 struct UBX_NAV_SVINFO
*svinfo
= &ubx
->payload
.nav_svinfo
;
456 svdata
.SatsInView
= 0;
458 // First, use slots for SVs actually being received
459 for (chan
= 0; chan
< svinfo
->numCh
; chan
++) {
460 if (svdata
.SatsInView
< GPSSATELLITES_PRN_NUMELEM
&& svinfo
->sv
[chan
].cno
> 0) {
461 svdata
.Azimuth
[svdata
.SatsInView
] = svinfo
->sv
[chan
].azim
;
462 svdata
.Elevation
[svdata
.SatsInView
] = svinfo
->sv
[chan
].elev
;
463 svdata
.PRN
[svdata
.SatsInView
] = svinfo
->sv
[chan
].svid
;
464 svdata
.SNR
[svdata
.SatsInView
] = svinfo
->sv
[chan
].cno
;
469 // Now try to add the rest
470 for (chan
= 0; chan
< svinfo
->numCh
; chan
++) {
471 if (svdata
.SatsInView
< GPSSATELLITES_PRN_NUMELEM
&& 0 == svinfo
->sv
[chan
].cno
) {
472 svdata
.Azimuth
[svdata
.SatsInView
] = svinfo
->sv
[chan
].azim
;
473 svdata
.Elevation
[svdata
.SatsInView
] = svinfo
->sv
[chan
].elev
;
474 svdata
.PRN
[svdata
.SatsInView
] = svinfo
->sv
[chan
].svid
;
475 svdata
.SNR
[svdata
.SatsInView
] = svinfo
->sv
[chan
].cno
;
480 // fill remaining slots (if any)
481 for (chan
= svdata
.SatsInView
; chan
< GPSSATELLITES_PRN_NUMELEM
; chan
++) {
482 svdata
.Azimuth
[chan
] = 0;
483 svdata
.Elevation
[chan
] = 0;
484 svdata
.PRN
[chan
] = 0;
485 svdata
.SNR
[chan
] = 0;
488 GPSSatellitesSet(&svdata
);
491 static void parse_ubx_ack_ack(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
493 struct UBX_ACK_ACK
*ack_ack
= &ubx
->payload
.ack_ack
;
495 ubxLastAck
= *ack_ack
;
498 static void parse_ubx_ack_nak(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
500 struct UBX_ACK_NAK
*ack_nak
= &ubx
->payload
.ack_nak
;
502 ubxLastNak
= *ack_nak
;
505 static void parse_ubx_mon_ver(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
507 struct UBX_MON_VER
*mon_ver
= &ubx
->payload
.mon_ver
;
509 ubxHwVersion
= atoi(mon_ver
->hwVersion
);
510 ubxSensorType
= (ubxHwVersion
>= UBX_HW_VERSION_8
) ? GPSPOSITIONSENSOR_SENSORTYPE_UBX8
:
511 ((ubxHwVersion
>= UBX_HW_VERSION_7
) ? GPSPOSITIONSENSOR_SENSORTYPE_UBX7
: GPSPOSITIONSENSOR_SENSORTYPE_UBX
);
512 // send sensor type right now because on UBX NEMA we don't get a full set of messages
513 // and we want to be able to see sensor type even on UBX NEMA GPS's
514 GPSPositionSensorSensorTypeSet((uint8_t *)&ubxSensorType
);
517 static void parse_ubx_op_sys(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
519 struct UBX_OP_SYSINFO
*sysinfo
= &ubx
->payload
.op_sysinfo
;
520 GPSExtendedStatusData data
;
522 data
.FlightTime
= sysinfo
->flightTime
;
523 data
.BoardType
[0] = sysinfo
->board_type
;
524 data
.BoardType
[1] = sysinfo
->board_revision
;
525 memcpy(&data
.FirmwareHash
, &sysinfo
->sha1sum
, GPSEXTENDEDSTATUS_FIRMWAREHASH_NUMELEM
);
526 memcpy(&data
.FirmwareTag
, &sysinfo
->commit_tag_name
, GPSEXTENDEDSTATUS_FIRMWARETAG_NUMELEM
);
527 data
.Options
= sysinfo
->options
;
528 data
.Status
= GPSEXTENDEDSTATUS_STATUS_GPSV9
;
529 GPSExtendedStatusSet(&data
);
532 static void parse_ubx_op_mag(struct UBXPacket
*ubx
, __attribute__((unused
)) GPSPositionSensorData
*GpsPosition
)
537 struct UBX_OP_MAG
*mag
= &ubx
->payload
.op_mag
;
538 float mags
[3] = { mag
->x
, mag
->y
, mag
->z
};
539 auxmagsupport_publish_samples(mags
, AUXMAGSENSOR_STATUS_OK
);
541 #endif /* if !defined(PIOS_GPS_MINIMAL) */
543 // UBX message parser
544 // returns UAVObjectID if a UAVObject structure is ready for further processing
545 uint32_t parse_ubx_message(struct UBXPacket
*ubx
, GPSPositionSensorData
*GpsPosition
)
548 static bool ubxInitialized
= false;
550 if (!ubxInitialized
) {
551 // initialize dop values. If no DOP sentence is received it is safer to initialize them to a high value rather than 0.
552 GpsPosition
->HDOP
= 99.99f
;
553 GpsPosition
->PDOP
= 99.99f
;
554 GpsPosition
->VDOP
= 99.99f
;
555 ubxInitialized
= true;
558 usePvt
= (lastPvtTime
) && (PIOS_DELAY_GetuSSince(lastPvtTime
) < UBX_PVT_TIMEOUT
* 1000);
559 for (uint8_t i
= 0; i
< UBX_HANDLER_TABLE_SIZE
; i
++) {
560 const ubx_message_handler
*handler
= &ubx_handler_table
[i
];
561 if (handler
->msgClass
== ubx
->header
.class && handler
->msgID
== ubx
->header
.id
) {
562 handler
->handler(ubx
, GpsPosition
);
567 GpsPosition
->SensorType
= ubxSensorType
;
569 if (msgtracker
.msg_received
== ALL_RECEIVED
) {
570 // leave BaudRate field alone!
571 GPSPositionSensorBaudRateGet(&GpsPosition
->BaudRate
);
572 GPSPositionSensorSet(GpsPosition
);
573 msgtracker
.msg_received
= NONE_RECEIVED
;
574 id
= GPSPOSITIONSENSOR_OBJID
;
577 GPSPositionSensorStatusGet(&status
);
578 if (status
== GPSPOSITIONSENSOR_STATUS_NOGPS
) {
579 // Some ubx thing has been received so GPS is there
581 // OP GPSV9 will sometimes cause this NOFIX
582 // because GPSV9 drops data which causes checksum errors which causes GPS.c to set the status to NOGPS
583 // see OP GPSV9 comment in parse_ubx_stream() for further information
584 status
= GPSPOSITIONSENSOR_STATUS_NOFIX
;
585 GPSPositionSensorStatusSet(&status
);
591 #if !defined(PIOS_GPS_MINIMAL)
592 void op_gpsv9_load_mag_settings()
594 if (auxmagsupport_get_type() == AUXMAGSETTINGS_TYPE_GPSV9
) {
600 #endif // !defined(PIOS_GPS_MINIMAL)
601 #endif // defined(PIOS_INCLUDE_GPS_UBX_PARSER)