Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
gps_ubx.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Antoine Drouin <poinix@gmail.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 
23 #include "subsystems/gps/gps_ubx.h"
24 #include "subsystems/abi.h"
25 #include "led.h"
26 
28 #include "ubx_protocol.h"
29 
30 /* parser status */
31 #define UNINIT 0
32 #define GOT_SYNC1 1
33 #define GOT_SYNC2 2
34 #define GOT_CLASS 3
35 #define GOT_ID 4
36 #define GOT_LEN1 5
37 #define GOT_LEN2 6
38 #define GOT_PAYLOAD 7
39 #define GOT_CHECKSUM1 8
40 
41 /* last error type */
42 #define GPS_UBX_ERR_NONE 0
43 #define GPS_UBX_ERR_OVERRUN 1
44 #define GPS_UBX_ERR_MSG_TOO_LONG 2
45 #define GPS_UBX_ERR_CHECKSUM 3
46 #define GPS_UBX_ERR_UNEXPECTED 4
47 #define GPS_UBX_ERR_OUT_OF_SYNC 5
48 
49 #define UTM_HEM_NORTH 0
50 #define UTM_HEM_SOUTH 1
51 
52 struct GpsUbx gps_ubx;
53 
54 #if USE_GPS_UBX_RXM_RAW
55 struct GpsUbxRaw gps_ubx_raw;
56 #endif
57 
59 
60 void gps_ubx_init(void)
61 {
63  gps_ubx.msg_available = false;
64  gps_ubx.error_cnt = 0;
66 
68 }
69 
70 void gps_ubx_event(void)
71 {
72  struct link_device *dev = &((UBX_GPS_LINK).device);
73 
74  while (dev->char_available(dev->periph)) {
75  gps_ubx_parse(dev->get_byte(dev->periph));
76  if (gps_ubx.msg_available) {
77  gps_ubx_msg();
78  }
79  }
80 }
81 
83 {
84 
85  if (gps_ubx.msg_class == UBX_NAV_ID) {
86  if (gps_ubx.msg_id == UBX_NAV_SOL_ID) {
87  /* get hardware clock ticks */
89  gps_ubx_time_sync.t0_tow = UBX_NAV_SOL_ITOW(gps_ubx.msg_buf);
90  gps_ubx_time_sync.t0_tow_frac = UBX_NAV_SOL_Frac(gps_ubx.msg_buf);
91  gps_ubx.state.tow = UBX_NAV_SOL_ITOW(gps_ubx.msg_buf);
92  gps_ubx.state.week = UBX_NAV_SOL_week(gps_ubx.msg_buf);
93  gps_ubx.state.fix = UBX_NAV_SOL_GPSfix(gps_ubx.msg_buf);
94  gps_ubx.state.ecef_pos.x = UBX_NAV_SOL_ECEF_X(gps_ubx.msg_buf);
95  gps_ubx.state.ecef_pos.y = UBX_NAV_SOL_ECEF_Y(gps_ubx.msg_buf);
96  gps_ubx.state.ecef_pos.z = UBX_NAV_SOL_ECEF_Z(gps_ubx.msg_buf);
98  gps_ubx.state.pacc = UBX_NAV_SOL_Pacc(gps_ubx.msg_buf);
99  gps_ubx.state.ecef_vel.x = UBX_NAV_SOL_ECEFVX(gps_ubx.msg_buf);
100  gps_ubx.state.ecef_vel.y = UBX_NAV_SOL_ECEFVY(gps_ubx.msg_buf);
101  gps_ubx.state.ecef_vel.z = UBX_NAV_SOL_ECEFVZ(gps_ubx.msg_buf);
103  gps_ubx.state.sacc = UBX_NAV_SOL_Sacc(gps_ubx.msg_buf);
104  gps_ubx.state.pdop = UBX_NAV_SOL_PDOP(gps_ubx.msg_buf);
105  gps_ubx.state.num_sv = UBX_NAV_SOL_numSV(gps_ubx.msg_buf);
106 #ifdef GPS_LED
107  if (gps_ubx.state.fix == GPS_FIX_3D) {
108  LED_ON(GPS_LED);
109  } else {
110  LED_TOGGLE(GPS_LED);
111  }
112 #endif
113  } else if (gps_ubx.msg_id == UBX_NAV_POSLLH_ID) {
114  gps_ubx.state.lla_pos.lat = UBX_NAV_POSLLH_LAT(gps_ubx.msg_buf);
115  gps_ubx.state.lla_pos.lon = UBX_NAV_POSLLH_LON(gps_ubx.msg_buf);
116  gps_ubx.state.lla_pos.alt = UBX_NAV_POSLLH_HEIGHT(gps_ubx.msg_buf);
118  gps_ubx.state.hmsl = UBX_NAV_POSLLH_HMSL(gps_ubx.msg_buf);
120  } else if (gps_ubx.msg_id == UBX_NAV_POSUTM_ID) {
121  gps_ubx.state.utm_pos.east = UBX_NAV_POSUTM_EAST(gps_ubx.msg_buf);
122  gps_ubx.state.utm_pos.north = UBX_NAV_POSUTM_NORTH(gps_ubx.msg_buf);
123  uint8_t hem = UBX_NAV_POSUTM_HEM(gps_ubx.msg_buf);
124  if (hem == UTM_HEM_SOUTH) {
125  gps_ubx.state.utm_pos.north -= 1000000000; /* Subtract false northing: -10000km */
126  }
127  gps_ubx.state.utm_pos.alt = UBX_NAV_POSUTM_ALT(gps_ubx.msg_buf) * 10;
128  gps_ubx.state.utm_pos.zone = UBX_NAV_POSUTM_ZONE(gps_ubx.msg_buf);
130 
133  } else if (gps_ubx.msg_id == UBX_NAV_VELNED_ID) {
134  gps_ubx.state.speed_3d = UBX_NAV_VELNED_Speed(gps_ubx.msg_buf);
135  gps_ubx.state.gspeed = UBX_NAV_VELNED_GSpeed(gps_ubx.msg_buf);
136  gps_ubx.state.ned_vel.x = UBX_NAV_VELNED_VEL_N(gps_ubx.msg_buf);
137  gps_ubx.state.ned_vel.y = UBX_NAV_VELNED_VEL_E(gps_ubx.msg_buf);
138  gps_ubx.state.ned_vel.z = UBX_NAV_VELNED_VEL_D(gps_ubx.msg_buf);
140  // Ublox gives I4 heading in 1e-5 degrees, apparenty from 0 to 360 degrees (not -180 to 180)
141  // I4 max = 2^31 = 214 * 1e5 * 100 < 360 * 1e7: overflow on angles over 214 deg -> casted to -214 deg
142  // solution: First to radians, and then scale to 1e-7 radians
143  // First x 10 for loosing less resolution, then to radians, then multiply x 10 again
144  gps_ubx.state.course = (RadOfDeg(UBX_NAV_VELNED_Heading(gps_ubx.msg_buf) * 10)) * 10;
146  gps_ubx.state.cacc = (RadOfDeg(UBX_NAV_VELNED_CAcc(gps_ubx.msg_buf) * 10)) * 10;
147  gps_ubx.state.tow = UBX_NAV_VELNED_ITOW(gps_ubx.msg_buf);
148  } else if (gps_ubx.msg_id == UBX_NAV_SVINFO_ID) {
149  gps_ubx.state.nb_channels = Min(UBX_NAV_SVINFO_NCH(gps_ubx.msg_buf), GPS_NB_CHANNELS);
150  uint8_t i;
151  for (i = 0; i < gps_ubx.state.nb_channels; i++) {
152  gps_ubx.state.svinfos[i].svid = UBX_NAV_SVINFO_SVID(gps_ubx.msg_buf, i);
153  gps_ubx.state.svinfos[i].flags = UBX_NAV_SVINFO_Flags(gps_ubx.msg_buf, i);
154  gps_ubx.state.svinfos[i].qi = UBX_NAV_SVINFO_QI(gps_ubx.msg_buf, i);
155  gps_ubx.state.svinfos[i].cno = UBX_NAV_SVINFO_CNO(gps_ubx.msg_buf, i);
156  gps_ubx.state.svinfos[i].elev = UBX_NAV_SVINFO_Elev(gps_ubx.msg_buf, i);
157  gps_ubx.state.svinfos[i].azim = UBX_NAV_SVINFO_Azim(gps_ubx.msg_buf, i);
158  }
159  } else if (gps_ubx.msg_id == UBX_NAV_STATUS_ID) {
160  gps_ubx.state.fix = UBX_NAV_STATUS_GPSfix(gps_ubx.msg_buf);
161  gps_ubx.status_flags = UBX_NAV_STATUS_Flags(gps_ubx.msg_buf);
162  gps_ubx.sol_flags = UBX_NAV_SOL_Flags(gps_ubx.msg_buf);
163  }
164  }
165 #if USE_GPS_UBX_RXM_RAW
166  else if (gps_ubx.msg_class == UBX_RXM_ID) {
167  if (gps_ubx.msg_id == UBX_RXM_RAW_ID) {
168  gps_ubx_raw.iTOW = UBX_RXM_RAW_iTOW(gps_ubx.msg_buf);
169  gps_ubx_raw.week = UBX_RXM_RAW_week(gps_ubx.msg_buf);
170  gps_ubx_raw.numSV = UBX_RXM_RAW_numSV(gps_ubx.msg_buf);
171  uint8_t i;
172  uint8_t max_SV = Min(gps_ubx_raw.numSV, GPS_UBX_NB_CHANNELS);
173  for (i = 0; i < max_SV; i++) {
174  gps_ubx_raw.measures[i].cpMes = UBX_RXM_RAW_cpMes(gps_ubx.msg_buf, i);
175  gps_ubx_raw.measures[i].prMes = UBX_RXM_RAW_prMes(gps_ubx.msg_buf, i);
176  gps_ubx_raw.measures[i].doMes = UBX_RXM_RAW_doMes(gps_ubx.msg_buf, i);
177  gps_ubx_raw.measures[i].sv = UBX_RXM_RAW_sv(gps_ubx.msg_buf, i);
178  gps_ubx_raw.measures[i].mesQI = UBX_RXM_RAW_mesQI(gps_ubx.msg_buf, i);
179  gps_ubx_raw.measures[i].cno = UBX_RXM_RAW_cno(gps_ubx.msg_buf, i);
180  gps_ubx_raw.measures[i].lli = UBX_RXM_RAW_lli(gps_ubx.msg_buf, i);
181  }
182  }
183  }
184 #endif
185 }
186 
187 #if LOG_RAW_GPS
189 #endif
190 
191 /* UBX parsing */
193 {
194 #if LOG_RAW_GPS
195  sdLogWriteByte(pprzLogFile, c);
196 #endif
197  if (gps_ubx.status < GOT_PAYLOAD) {
198  gps_ubx.ck_a += c;
200  }
201  switch (gps_ubx.status) {
202  case UNINIT:
203  if (c == UBX_SYNC1) {
204  gps_ubx.status++;
205  }
206  break;
207  case GOT_SYNC1:
208  if (c != UBX_SYNC2) {
210  goto error;
211  }
212  gps_ubx.ck_a = 0;
213  gps_ubx.ck_b = 0;
214  gps_ubx.status++;
215  break;
216  case GOT_SYNC2:
217  if (gps_ubx.msg_available) {
218  /* Previous message has not yet been parsed: discard this one */
220  goto error;
221  }
222  gps_ubx.msg_class = c;
223  gps_ubx.status++;
224  break;
225  case GOT_CLASS:
226  gps_ubx.msg_id = c;
227  gps_ubx.status++;
228  break;
229  case GOT_ID:
230  gps_ubx.len = c;
231  gps_ubx.status++;
232  break;
233  case GOT_LEN1:
234  gps_ubx.len |= (c << 8);
237  goto error;
238  }
239  gps_ubx.msg_idx = 0;
240  gps_ubx.status++;
241  break;
242  case GOT_LEN2:
244  gps_ubx.msg_idx++;
245  if (gps_ubx.msg_idx >= gps_ubx.len) {
246  gps_ubx.status++;
247  }
248  break;
249  case GOT_PAYLOAD:
250  if (c != gps_ubx.ck_a) {
252  goto error;
253  }
254  gps_ubx.status++;
255  break;
256  case GOT_CHECKSUM1:
257  if (c != gps_ubx.ck_b) {
259  goto error;
260  }
261  gps_ubx.msg_available = true;
262  goto restart;
263  break;
264  default:
266  goto error;
267  }
268  return;
269 error:
270  gps_ubx.error_cnt++;
271 restart:
273  return;
274 }
275 
276 static void ubx_send_1byte(struct link_device *dev, uint8_t byte)
277 {
278  dev->put_byte(dev->periph, 0, byte);
281 }
282 
283 void ubx_header(struct link_device *dev, uint8_t nav_id, uint8_t msg_id, uint16_t len)
284 {
285  dev->put_byte(dev->periph, 0, UBX_SYNC1);
286  dev->put_byte(dev->periph, 0, UBX_SYNC2);
287  gps_ubx.send_ck_a = 0;
288  gps_ubx.send_ck_b = 0;
289  ubx_send_1byte(dev, nav_id);
290  ubx_send_1byte(dev, msg_id);
291  ubx_send_1byte(dev, (uint8_t)(len&0xFF));
292  ubx_send_1byte(dev, (uint8_t)(len>>8));
293 }
294 
295 void ubx_trailer(struct link_device *dev)
296 {
297  dev->put_byte(dev->periph, 0, gps_ubx.send_ck_a);
298  dev->put_byte(dev->periph, 0, gps_ubx.send_ck_b);
299  dev->send_message(dev->periph, 0);
300 }
301 
302 void ubx_send_bytes(struct link_device *dev, uint8_t len, uint8_t *bytes)
303 {
304  int i;
305  for (i = 0; i < len; i++) {
306  ubx_send_1byte(dev, bytes[i]);
307  }
308 }
309 
310 void ubx_send_cfg_rst(struct link_device *dev, uint16_t bbr , uint8_t reset_mode)
311 {
312 #ifdef UBX_GPS_LINK
313  UbxSend_CFG_RST(dev, bbr, reset_mode, 0x00);
314 #endif /* else less harmful for HITL */
315 }
316 
317 #ifndef GPS_UBX_UCENTER
318 #define gps_ubx_ucenter_event() {}
319 #else
321 #endif
322 
323 void gps_ubx_msg(void)
324 {
325  // current timestamp
326  uint32_t now_ts = get_sys_time_usec();
327 
332  if (gps_ubx.msg_class == UBX_NAV_ID &&
333  (gps_ubx.msg_id == UBX_NAV_VELNED_ID ||
334  (gps_ubx.msg_id == UBX_NAV_SOL_ID &&
336  if (gps_ubx.state.fix == GPS_FIX_3D) {
339  }
340  AbiSendMsgGPS(GPS_UBX_ID, now_ts, &gps_ubx.state);
341  }
342  gps_ubx.msg_available = false;
343 }
344 
uint8_t qi
quality bitfield (GPS receiver specific)
Definition: gps.h:74
unsigned short uint16_t
Definition: types.h:16
#define GOT_CLASS
Definition: gps_ubx.c:34
int32_t z
in centimeters
#define UTM_HEM_SOUTH
Definition: gps_ubx.c:50
uint32_t t0_tow
GPS time of week in ms from last message.
Definition: gps.h:115
int32_t north
in centimeters
struct SVinfo svinfos[GPS_NB_CHANNELS]
holds information from the Space Vehicles (Satellites)
Definition: gps.h:104
int16_t azim
azimuth in deg
Definition: gps.h:77
#define GOT_CHECKSUM1
Definition: gps_ubx.c:39
uint32_t pacc
position accuracy in cm
Definition: gps.h:94
#define GOT_ID
Definition: gps_ubx.c:35
void ubx_trailer(struct link_device *dev)
Definition: gps_ubx.c:295
void ubx_send_bytes(struct link_device *dev, uint8_t len, uint8_t *bytes)
Definition: gps_ubx.c:302
#define gps_ubx_ucenter_event()
Definition: gps_ubx.c:318
void gps_ubx_event(void)
Definition: gps_ubx.c:70
uint8_t nb_channels
Number of scanned satellites.
Definition: gps.h:103
uint32_t t0_ticks
hw clock ticks when GPS message is received
Definition: gps.h:117
#define GPS_VALID_VEL_NED_BIT
Definition: gps.h:52
uint8_t sol_flags
Definition: gps_ubx.h:69
uint8_t valid_fields
bitfield indicating valid fields (GPS_VALID_x_BIT)
Definition: gps.h:82
int32_t y
in centimeters
uint16_t week
GPS week.
Definition: gps.h:100
UBX protocol specific code.
Definition: gps_ubx.h:54
#define GPS_NB_CHANNELS
Definition: gps.h:57
void gps_ubx_parse(uint8_t c)
Definition: gps_ubx.c:192
#define GPS_UBX_ID
Main include for ABI (AirBorneInterface).
void gps_ubx_init(void)
Definition: gps_ubx.c:60
uint16_t len
Definition: gps_ubx.h:61
struct GpsUbx gps_ubx
Definition: gps_ubx.c:52
uint8_t msg_buf[GPS_UBX_MAX_PAYLOAD]
Definition: gps_ubx.h:56
int32_t east
in centimeters
uint8_t svid
Satellite ID.
Definition: gps.h:72
volatile uint32_t nb_tick
SYS_TIME_TICKS since startup.
Definition: sys_time.h:74
uint16_t speed_3d
norm of 3d speed in cm/s
Definition: gps.h:92
#define GPS_FIX_3D
3D GPS fix
Definition: gps.h:39
int32_t z
Down.
struct UtmCoor_i utm_pos
position in UTM (north,east: cm; alt: mm over MSL)
Definition: gps.h:87
static void ubx_send_1byte(struct link_device *dev, uint8_t byte)
Definition: gps_ubx.c:276
#define GPS_UBX_ERR_OUT_OF_SYNC
Definition: gps_ubx.c:47
uint8_t msg_id
Definition: gps_ubx.h:57
uint8_t error_cnt
Definition: gps_ubx.h:65
uint32_t last_3dfix_ticks
cpu time ticks at last valid 3D fix
Definition: gps.h:106
int8_t elev
elevation in deg
Definition: gps.h:76
int32_t alt
in millimeters above WGS84 reference ellipsoid
#define GPS_UBX_MAX_PAYLOAD
Definition: gps_ubx.h:53
uint32_t sacc
speed accuracy in cm/s
Definition: gps.h:95
struct GpsTimeSync gps_ubx_time_sync
Definition: gps_ubx.c:58
int32_t y
East.
#define GOT_SYNC2
Definition: gps_ubx.c:33
uint32_t last_msg_time
cpu time in sec at last received GPS message
Definition: gps.h:109
uint32_t cacc
course accuracy in rad*1e7
Definition: gps.h:96
uint8_t zone
UTM zone number.
#define GPS_VALID_COURSE_BIT
Definition: gps.h:54
Configure Ublox GPS.
#define GPS_UBX_ERR_UNEXPECTED
Definition: gps_ubx.c:46
int32_t hmsl
height above mean sea level (MSL) in mm
Definition: gps.h:88
uint8_t cno
Carrier to Noise Ratio (Signal Strength) in dbHz.
Definition: gps.h:75
uint32_t tow
GPS time of week in ms.
Definition: gps.h:101
uint8_t ck_b
Definition: gps_ubx.h:63
uint16_t pdop
position dilution of precision scaled by 100
Definition: gps.h:97
uint8_t ck_a
Definition: gps_ubx.h:63
void ubx_header(struct link_device *dev, uint8_t nav_id, uint8_t msg_id, uint16_t len)
Definition: gps_ubx.c:283
int32_t x
North.
unsigned long uint32_t
Definition: types.h:18
#define GPS_UBX_NB_CHANNELS
Definition: gps_ubx.h:51
struct EcefCoor_i ecef_pos
position in ECEF in cm
Definition: gps.h:85
void ubx_send_cfg_rst(struct link_device *dev, uint16_t bbr, uint8_t reset_mode)
Definition: gps_ubx.c:310
#define GPS_VALID_HMSL_BIT
Definition: gps.h:53
uint8_t msg_idx
Definition: gps_ubx.h:62
int32_t lon
in degrees*1e7
FileDes pprzLogFile
Definition: sdlog_chibios.c:76
#define GPS_UBX_ERR_MSG_TOO_LONG
Definition: gps_ubx.c:44
#define Min(x, y)
Definition: main_fbw.c:52
volatile uint32_t nb_sec_rem
remainder of seconds since startup in CPU_TICKS
Definition: sys_time.h:73
#define LED_TOGGLE(i)
Definition: led_hw.h:51
uint8_t send_ck_b
Definition: gps_ubx.h:64
bool msg_available
Definition: gps_ubx.h:55
uint8_t status
Definition: gps_ubx.h:60
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:73
void gps_ubx_read_message(void)
Definition: gps_ubx.c:82
uint8_t status_flags
Definition: gps_ubx.h:68
uint32_t last_3dfix_time
cpu time in sec at last valid 3D fix
Definition: gps.h:107
int32_t alt
in millimeters (above WGS84 reference ellipsoid or above MSL)
#define GOT_LEN1
Definition: gps_ubx.c:36
unsigned char uint8_t
Definition: types.h:14
#define GPS_UBX_ERR_OVERRUN
Definition: gps_ubx.c:43
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition: gps.h:93
#define GOT_PAYLOAD
Definition: gps_ubx.c:38
uint8_t comp_id
id of current gps
Definition: gps.h:83
#define byte
volatile uint32_t nb_sec
full seconds since startup
Definition: sys_time.h:72
int32_t t0_tow_frac
fractional ns remainder of tow [ms], range -500000 .. 500000
Definition: gps.h:116
#define GPS_VALID_POS_ECEF_BIT
Definition: gps.h:48
struct GpsState state
Definition: gps_ubx.h:71
uint8_t flags
bitfield with GPS receiver specific flags
Definition: gps.h:73
uint32_t last_msg_ticks
cpu time ticks at last received GPS message
Definition: gps.h:108
#define GPS_VALID_POS_LLA_BIT
Definition: gps.h:49
#define GOT_LEN2
Definition: gps_ubx.c:37
uint8_t num_sv
number of sat in fix
Definition: gps.h:98
arch independent LED (Light Emitting Diodes) API
int32_t x
in centimeters
#define UNINIT
Includes macros generated from ubx.xml.
Definition: gps_ubx.c:31
uint16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:91
#define LED_ON(i)
Definition: led_hw.h:49
struct EcefCoor_i ecef_vel
speed ECEF in cm/s
Definition: gps.h:89
data structure for GPS time sync
Definition: gps.h:114
uint8_t send_ck_a
Definition: gps_ubx.h:64
#define GPS_VALID_VEL_ECEF_BIT
Definition: gps.h:51
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:86
void gps_ubx_msg(void)
Definition: gps_ubx.c:323
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:68
int32_t lat
in degrees*1e7
uint8_t fix
status of fix
Definition: gps.h:99
uint8_t error_last
Definition: gps_ubx.h:66
#define GPS_VALID_POS_UTM_BIT
Definition: gps.h:50
#define GOT_SYNC1
Definition: gps_ubx.c:32
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:90
#define GPS_UBX_ERR_NONE
Definition: gps_ubx.c:42
uint8_t msg_class
Definition: gps_ubx.h:58
#define GPS_UBX_ERR_CHECKSUM
Definition: gps_ubx.c:45