Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
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 "modules/gps/gps_ubx.h"
24 #include "modules/core/abi.h"
25 #include "pprzlink/dl_protocol.h"
26 #include "led.h"
27 
28 #ifndef USE_GPS_UBX_RTCM
29 #define USE_GPS_UBX_RTCM 0
30 #endif
31 
32 
33 #if USE_GPS_UBX_RTCM
35 #define RTCM3_PREAMBLE 0xD3
36 #define RTCM3_MSG_1005 0x69
37 #define RTCM3_MSG_1077 0xB1
38 #define RTCM3_MSG_4072 0x72
39 #define RTCM3_MSG_1230 0xE6
40 #define RTCM3_MSG_1087 0xBB
41 #endif
42 
43 #if PRINT_DEBUG_GPS_UBX
44 #define DEBUG_PRINT(...) printf(__VA_ARGS__)
45 #else
46 #define DEBUG_PRINT(...) {}
47 #endif
48 
50 #include "ubx_protocol.h"
51 
52 /* parser status */
53 #define UNINIT 0
54 #define GOT_SYNC1 1
55 #define GOT_SYNC2 2
56 #define GOT_CLASS 3
57 #define GOT_ID 4
58 #define GOT_LEN1 5
59 #define GOT_LEN2 6
60 #define GOT_PAYLOAD 7
61 #define GOT_CHECKSUM1 8
62 
63 #define RXM_RTCM_VERSION 0x02
64 #define NAV_RELPOSNED_VERSION 0x01
65 /* last error type */
66 #define GPS_UBX_ERR_NONE 0
67 #define GPS_UBX_ERR_OVERRUN 1
68 #define GPS_UBX_ERR_MSG_TOO_LONG 2
69 #define GPS_UBX_ERR_CHECKSUM 3
70 #define GPS_UBX_ERR_UNEXPECTED 4
71 #define GPS_UBX_ERR_OUT_OF_SYNC 5
72 
73 #define UTM_HEM_NORTH 0
74 #define UTM_HEM_SOUTH 1
75 
76 struct GpsUbx gps_ubx[GPS_UBX_NB];
78 void gps_ubx_parse(struct GpsUbx *gubx, uint8_t c);
79 void gps_ubx_msg(struct GpsUbx *gubx);
80 
81 #if USE_GPS_UBX_RTCM
82 extern struct RtcmMan rtcm_man;
83 
84 #ifndef INJECT_BUFF_SIZE
85 #define INJECT_BUFF_SIZE 1024 + 6
86 #endif
87 
88 /* RTCM control struct type */
89 struct rtcm_t {
90  uint32_t nbyte;
91  uint32_t len;
92  uint8_t buff[INJECT_BUFF_SIZE];
93 };
94 struct rtcm_t rtcm = { 0 };
95 
96 #endif
97 
98 /*
99  * GPS Reset
100  */
101 #ifndef GPS_UBX_BOOTRESET
102 #define GPS_UBX_BOOTRESET 0
103 #endif
104 
105 #define CFG_RST_Reset_Hardware 0x00
106 #define CFG_RST_Reset_Controlled 0x01
107 #define CFG_RST_Reset_Controlled_GPS_only 0x02
108 #define CFG_RST_Reset_Controlled_GPS_stop 0x08
109 #define CFG_RST_Reset_Controlled_GPS_start 0x09
110 
111 #define CFG_RST_BBR_Hotstart 0x0000
112 #define CFG_RST_BBR_Warmstart 0x0001
113 #define CFG_RST_BBR_Coldstart 0xffff
114 
115 void gps_ubx_init(void)
116 {
118 
119  // Configure the devices
121  gps_ubx[0].dev = &(UBX_GPS_PORT).device;
122 #if GPS_UBX_NB > 1
124  gps_ubx[1].dev = &(UBX2_GPS_PORT).device;
125 #endif
126 
127  // Set the defaults
128  for(uint8_t i = 0; i < GPS_UBX_NB; i++) {
129  gps_ubx[i].status = UNINIT;
130  gps_ubx[i].msg_available = false;
131  gps_ubx[i].error_cnt = 0;
133  gps_ubx[i].pacc_valid = false;
134  }
135 }
136 
137 void gps_ubx_event(void)
138 {
139  for(uint8_t i = 0; i < GPS_UBX_NB; i++) {
140  struct link_device *dev = gps_ubx[i].dev;
141 
142  // Read all available bytes from the device
143  while (dev->char_available(dev->periph)) {
144  gps_ubx_parse(&gps_ubx[i], dev->get_byte(dev->periph));
145  if (gps_ubx[i].msg_available) {
146  gps_ubx_msg(&gps_ubx[i]);
147  }
148  }
149 
150  // Reset the GPS's if needed
151  if (gps_ubx_reset > 0) {
152  switch (gps_ubx_reset) {
156  default: DEBUG_PRINT("Unknown reset id: %i", gps_ubx[i].reset); break;
157  }
158  }
159  }
160 
161  gps_ubx_reset = 0;
162 }
163 
165 {
167  if (gps_ubx[0].msg_available) {
168  gps_ubx[0].error_cnt++;
170  } else {
171  gps_ubx[0].msg_class = DL_HITL_UBX_class(buf);
172  gps_ubx[0].msg_id = DL_HITL_UBX_id(buf);
173  uint8_t l = DL_HITL_UBX_ubx_payload_length(buf);
174  uint8_t *ubx_payload = DL_HITL_UBX_ubx_payload(buf);
175  memcpy(gps_ubx[0].msg_buf, ubx_payload, l);
176  gps_ubx[0].msg_available = true;
177  }
178 }
179 
180 static void gps_ubx_parse_nav_pvt(struct GpsUbx *gubx)
181 {
182  uint8_t flags = UBX_NAV_PVT_flags(gubx->msg_buf);
183 
184  // Copy fix information
185  uint8_t gnssFixOK = bit_is_set(flags, 0);
186  uint8_t diffSoln = bit_is_set(flags, 1);
187  uint8_t carrSoln = (flags & 0xC0) >> 6;
188  if (diffSoln && carrSoln == 2) {
189  gubx->state.fix = 5; // rtk
190  } else if(diffSoln && carrSoln == 1) {
191  gubx->state.fix = 4; // dgnss
192  } else if(gnssFixOK) {
193  gubx->state.fix = 3; // 3D
194  } else {
195  gubx->state.fix = 0;
196  }
197 
198  // Copy time information
199  gubx->state.tow = UBX_NAV_PVT_iTOW(gubx->msg_buf);
200  uint16_t year = UBX_NAV_PVT_year(gubx->msg_buf);
201  uint8_t month = UBX_NAV_PVT_month(gubx->msg_buf);
202  uint8_t day = UBX_NAV_PVT_day(gubx->msg_buf);
203  gubx->state.week = gps_week_number(year, month, day);
204  gubx->state.num_sv = UBX_NAV_PVT_numSV(gubx->msg_buf);
205 
206  // Copy LLA position
207  gubx->state.lla_pos.lat = UBX_NAV_PVT_lat(gubx->msg_buf);
208  gubx->state.lla_pos.lon = UBX_NAV_PVT_lon(gubx->msg_buf);
209  gubx->state.lla_pos.alt = UBX_NAV_PVT_height(gubx->msg_buf);
211 
212  // Ublox gives I4 heading in 1e-5 degrees, apparenty from 0 to 360 degrees (not -180 to 180)
213  // I4 max = 2^31 = 214 * 1e5 * 100 < 360 * 1e7: overflow on angles over 214 deg -> casted to -214 deg
214  // solution: First to radians, and then scale to 1e-7 radians
215  // First x 10 for loosing less resolution, then to radians, then multiply x 10 again
216  gubx->state.course = (RadOfDeg(UBX_NAV_PVT_headMot(gubx->msg_buf) * 10)) * 10;
217  SetBit(gubx->state.valid_fields, GPS_VALID_COURSE_BIT);
218  gubx->state.cacc = (RadOfDeg(UBX_NAV_PVT_headAcc(gubx->msg_buf) * 10)) * 10;
219 
220  // Copy HMSL and ground speed
221  gubx->state.hmsl = UBX_NAV_PVT_hMSL(gubx->msg_buf);
222  SetBit(gubx->state.valid_fields, GPS_VALID_HMSL_BIT);
223  gubx->state.gspeed = UBX_NAV_PVT_gSpeed(gubx->msg_buf) / 10;
224 
225  // Copy NED velocities
226  gubx->state.ned_vel.x = UBX_NAV_PVT_velN(gubx->msg_buf) / 10;
227  gubx->state.ned_vel.y = UBX_NAV_PVT_velE(gubx->msg_buf) / 10;
228  gubx->state.ned_vel.z = UBX_NAV_PVT_velD(gubx->msg_buf) / 10;
230 
231  // Copy accuracy information
232  gubx->state.pdop = UBX_NAV_PVT_pDOP(gubx->msg_buf);
233  gubx->state.hacc = UBX_NAV_PVT_hAcc(gubx->msg_buf) / 10;
234  gubx->state.vacc = UBX_NAV_PVT_vAcc(gubx->msg_buf) / 10;
235  gubx->state.sacc = UBX_NAV_PVT_sAcc(gubx->msg_buf) / 10;
236 
237  if (!gubx->pacc_valid) {
238  // workaround for PVT only
239  gubx->state.pacc = gubx->state.hacc; // report horizontal accuracy
240  }
241 }
242 
243 static void gps_ubx_parse_nav_sol(struct GpsUbx *gubx)
244 {
245  // Copy time and fix information
246  uint8_t fix = UBX_NAV_SOL_gpsFix(gubx->msg_buf);
247  if ((fix == GPS_FIX_3D && fix > gubx->state.fix) || fix < GPS_FIX_3D) {
248  // update only if fix is better than current or fix not 3D
249  // leaving fix if in GNSS or RTK mode
250  gubx->state.fix = fix;
251  }
252  gubx->state.tow = UBX_NAV_SOL_iTOW(gubx->msg_buf);
253  gubx->state.week = UBX_NAV_SOL_week(gubx->msg_buf);
254  gubx->state.num_sv = UBX_NAV_SOL_numSV(gubx->msg_buf);
255 
256  // Copy ecef position
257  gubx->state.ecef_pos.x = UBX_NAV_SOL_ecefX(gubx->msg_buf);
258  gubx->state.ecef_pos.y = UBX_NAV_SOL_ecefY(gubx->msg_buf);
259  gubx->state.ecef_pos.z = UBX_NAV_SOL_ecefZ(gubx->msg_buf);
261 
262  // Copy ecef velocity
263  gubx->state.ecef_vel.x = UBX_NAV_SOL_ecefVX(gubx->msg_buf);
264  gubx->state.ecef_vel.y = UBX_NAV_SOL_ecefVY(gubx->msg_buf);
265  gubx->state.ecef_vel.z = UBX_NAV_SOL_ecefVZ(gubx->msg_buf);
267 
268  // Copy accuracy measurements
269  gubx->state.pacc = UBX_NAV_SOL_pAcc(gubx->msg_buf);
270  gubx->state.sacc = UBX_NAV_SOL_sAcc(gubx->msg_buf);
271  gubx->state.pdop = UBX_NAV_SOL_pDOP(gubx->msg_buf);
272  gubx->pacc_valid = true;
273 }
274 
275 static void gps_ubx_parse_nav_posecef(struct GpsUbx *gubx)
276 {
277  gubx->state.tow = UBX_NAV_POSECEF_iTOW(gubx->msg_buf);
278 
279  // Copy ecef position
280  gubx->state.ecef_pos.x = UBX_NAV_POSECEF_ecefX(gubx->msg_buf);
281  gubx->state.ecef_pos.y = UBX_NAV_POSECEF_ecefY(gubx->msg_buf);
282  gubx->state.ecef_pos.z = UBX_NAV_POSECEF_ecefZ(gubx->msg_buf);
284 
285  // Copy accuracy information
286  gubx->state.pacc = UBX_NAV_POSECEF_pAcc(gubx->msg_buf);
287  gubx->pacc_valid = true;
288 }
289 
290 static void gps_ubx_parse_nav_posllh(struct GpsUbx *gubx)
291 {
292  // Copy LLA position
293  gubx->state.lla_pos.lat = UBX_NAV_POSLLH_lat(gubx->msg_buf);
294  gubx->state.lla_pos.lon = UBX_NAV_POSLLH_lon(gubx->msg_buf);
295  gubx->state.lla_pos.alt = UBX_NAV_POSLLH_height(gubx->msg_buf);
297 
298  // Copy HMSL
299  gubx->state.hmsl = UBX_NAV_POSLLH_hMSL(gubx->msg_buf);
300  SetBit(gubx->state.valid_fields, GPS_VALID_HMSL_BIT);
301 
302  // Copy accuracy information
303  gubx->state.hacc = UBX_NAV_POSLLH_hAcc(gubx->msg_buf) / 10;
304  gubx->state.vacc = UBX_NAV_POSLLH_vAcc(gubx->msg_buf) / 10;
305 }
306 
307 static void gps_ubx_parse_nav_posutm(struct GpsUbx *gubx)
308 {
309  uint8_t hem = UBX_NAV_POSUTM_hem(gubx->msg_buf);
310 
311  // Copy UTM state
312  gubx->state.utm_pos.east = UBX_NAV_POSUTM_east(gubx->msg_buf);
313  gubx->state.utm_pos.north = UBX_NAV_POSUTM_north(gubx->msg_buf);
314  if (hem == UTM_HEM_SOUTH) {
315  gubx->state.utm_pos.north -= 1000000000; /* Subtract false northing: -10000km */
316  }
317  gubx->state.utm_pos.alt = UBX_NAV_POSUTM_alt(gubx->msg_buf) * 10;
318  gubx->state.utm_pos.zone = UBX_NAV_POSUTM_zone(gubx->msg_buf);
320 
321  // Copy HMSL
322  gubx->state.hmsl = gubx->state.utm_pos.alt;
323  SetBit(gubx->state.valid_fields, GPS_VALID_HMSL_BIT);
324 }
325 
326 static void gps_ubx_parse_velecef(struct GpsUbx *gubx)
327 {
328  gubx->state.tow = UBX_NAV_VELECEF_iTOW(gubx->msg_buf);
329 
330  // Copy ecef velocity
331  gubx->state.ecef_vel.x = UBX_NAV_VELECEF_ecefVX(gubx->msg_buf);
332  gubx->state.ecef_vel.y = UBX_NAV_VELECEF_ecefVY(gubx->msg_buf);
333  gubx->state.ecef_vel.z = UBX_NAV_VELECEF_ecefVZ(gubx->msg_buf);
335 
336  // Copy accuracy measurements
337  gubx->state.sacc = UBX_NAV_VELECEF_sAcc(gubx->msg_buf);
338 }
339 
340 static void gps_ubx_parse_nav_velned(struct GpsUbx *gubx)
341 {
342  // Copy groundspeed and total 3d speed
343  gubx->state.speed_3d = UBX_NAV_VELNED_speed(gubx->msg_buf);
344  gubx->state.gspeed = UBX_NAV_VELNED_gSpeed(gubx->msg_buf);
345 
346  // Copy NED velocities
347  gubx->state.ned_vel.x = UBX_NAV_VELNED_velN(gubx->msg_buf);
348  gubx->state.ned_vel.y = UBX_NAV_VELNED_velE(gubx->msg_buf);
349  gubx->state.ned_vel.z = UBX_NAV_VELNED_velD(gubx->msg_buf);
351 
352  // Copy course
353  gubx->state.course = (RadOfDeg(UBX_NAV_VELNED_heading(gubx->msg_buf) * 10)) * 10;
354  gubx->state.cacc = (RadOfDeg(UBX_NAV_VELNED_cAcc(gubx->msg_buf) * 10)) * 10;
355  SetBit(gubx->state.valid_fields, GPS_VALID_COURSE_BIT);
356 
357  // Copy time of week
358  gubx->state.tow = UBX_NAV_VELNED_iTOW(gubx->msg_buf);
359 }
360 
361 static void gps_ubx_parse_nav_svinfo(struct GpsUbx *gubx)
362 {
363  // Get the number of channels
364  gubx->state.nb_channels = Min(UBX_NAV_SVINFO_numCh(gubx->msg_buf), GPS_NB_CHANNELS);
365 
366  // Go through all the different channels
367  for (uint8_t i = 0; i < gubx->state.nb_channels; i++) {
368  gubx->state.svinfos[i].svid = UBX_NAV_SVINFO_svid(gubx->msg_buf, i);
369  gubx->state.svinfos[i].flags = UBX_NAV_SVINFO_flags(gubx->msg_buf, i);
370  gubx->state.svinfos[i].qi = UBX_NAV_SVINFO_quality(gubx->msg_buf, i);
371  gubx->state.svinfos[i].cno = UBX_NAV_SVINFO_cno(gubx->msg_buf, i);
372  gubx->state.svinfos[i].elev = UBX_NAV_SVINFO_elev(gubx->msg_buf, i);
373  gubx->state.svinfos[i].azim = UBX_NAV_SVINFO_azim(gubx->msg_buf, i);
374  }
375 }
376 
377 static void gps_ubx_parse_nav_sat(struct GpsUbx *gubx)
378 {
379  // Get the number of channels(sattelites) and time of week
380  gubx->state.tow = UBX_NAV_SAT_iTOW(gubx->msg_buf);
381  gubx->state.nb_channels = Min(UBX_NAV_SAT_numSvs(gubx->msg_buf), GPS_NB_CHANNELS);
382 
383  // Check the version
384  uint8_t version = UBX_NAV_SAT_version(gubx->msg_buf);
385  if (version != 1) {
386  return;
387  }
388 
389  // Go through all the different channels
390  for (uint8_t i = 0; i < gubx->state.nb_channels; i++) {
391  uint32_t flags = UBX_NAV_SVINFO_flags(gubx->msg_buf, i);
392  gubx->state.svinfos[i].svid = UBX_NAV_SAT_svId(gubx->msg_buf, i);
393  gubx->state.svinfos[i].cno = UBX_NAV_SAT_cno(gubx->msg_buf, i);
394  gubx->state.svinfos[i].elev = UBX_NAV_SAT_elev(gubx->msg_buf, i);
395  gubx->state.svinfos[i].azim = UBX_NAV_SAT_azim(gubx->msg_buf, i);
396  gubx->state.svinfos[i].qi = flags & 0x7;
397  gubx->state.svinfos[i].flags = (flags >> 3) & 0x1;
398  }
399 }
400 
401 static void gps_ubx_parse_nav_status(struct GpsUbx *gubx)
402 {
403  uint8_t fix = UBX_NAV_STATUS_gpsFix(gubx->msg_buf);
404  if ((fix == GPS_FIX_3D && fix > gubx->state.fix) || fix < GPS_FIX_3D) {
405  // update only if fix is better than current or fix not 3D
406  // leaving fix if in GNSS or RTK mode
407  gubx->state.fix = fix;
408  }
409  gubx->state.tow = UBX_NAV_STATUS_iTOW(gubx->msg_buf);
410  gubx->status_flags = UBX_NAV_STATUS_flags(gubx->msg_buf);
411 }
412 
413 static void gps_ubx_parse_nav_relposned(struct GpsUbx *gubx)
414 {
415 #if USE_GPS_UBX_RTCM
416  uint8_t version = UBX_NAV_RELPOSNED_version(gubx->msg_buf);
417  if (version <= NAV_RELPOSNED_VERSION) {
418  uint8_t flags = UBX_NAV_RELPOSNED_flags(gubx->msg_buf);
419  uint8_t carrSoln = RTCMgetbitu(&flags, 3, 2);
420  uint8_t relPosValid = RTCMgetbitu(&flags, 5, 1);
421  uint8_t diffSoln = RTCMgetbitu(&flags, 6, 1);
422  uint8_t gnssFixOK = RTCMgetbitu(&flags, 7, 1);
423 
424  /* Only save the latest valid relative position */
425  if (relPosValid) {
426  if (diffSoln && carrSoln == 2) {
427  gubx->state.fix = 5; // rtk
428  } else if(diffSoln && carrSoln == 1) {
429  gubx->state.fix = 4; // dgnss
430  } else if(gnssFixOK) {
431  gubx->state.fix = 3; // 3D
432  } else {
433  gubx->state.fix = 0;
434  }
435 
436  uint32_t now_ts = get_sys_time_usec();
437  struct RelPosNED relpos = {0};
438  relpos.reference_id = UBX_NAV_RELPOSNED_refStationId(gubx->msg_buf);
439  relpos.tow = UBX_NAV_RELPOSNED_iTOW(gubx->msg_buf);
440  relpos.pos.x = UBX_NAV_RELPOSNED_relPosN(gubx->msg_buf) * 1e-2 + UBX_NAV_RELPOSNED_relPosHPN(gubx->msg_buf) * 1e-4;
441  relpos.pos.y = UBX_NAV_RELPOSNED_relPosE(gubx->msg_buf) * 1e-2 + UBX_NAV_RELPOSNED_relPosHPE(gubx->msg_buf) * 1e-4;
442  relpos.pos.z = UBX_NAV_RELPOSNED_relPosD(gubx->msg_buf) * 1e-2 + UBX_NAV_RELPOSNED_relPosHPD(gubx->msg_buf) * 1e-4;
443  relpos.distance = UBX_NAV_RELPOSNED_relPosLength(gubx->msg_buf) * 1e-2;
444  relpos.heading = RadOfDeg(UBX_NAV_RELPOSNED_relPosHeading(gubx->msg_buf) * 1e-5);
445  relpos.pos_acc.x = UBX_NAV_RELPOSNED_accN(gubx->msg_buf) * 1e-4;
446  relpos.pos_acc.y = UBX_NAV_RELPOSNED_accE(gubx->msg_buf) * 1e-4;
447  relpos.pos_acc.z = UBX_NAV_RELPOSNED_accD(gubx->msg_buf) * 1e-4;
448  relpos.distance_acc = UBX_NAV_RELPOSNED_accLength(gubx->msg_buf) * 1e-4;
449  relpos.heading_acc = RadOfDeg(UBX_NAV_RELPOSNED_accHeading(gubx->msg_buf) * 1e-5);
450 
451  AbiSendMsgRELPOS(gubx->state.comp_id, now_ts, &relpos);
452  }
453  }
454 #else
455  (void)gubx;
456 #endif
457 }
458 
459 void gps_ubx_read_message(struct GpsUbx *gubx);
460 void gps_ubx_read_message(struct GpsUbx *gubx)
461 {
462 
463  if (gubx->msg_class == UBX_NAV_ID) {
464  switch (gubx->msg_id) {
465  case UBX_NAV_POSECEF_ID:
467  break;
468  case UBX_NAV_POSLLH_ID:
470  break;
471  case UBX_NAV_STATUS_ID:
473  break;
474  case UBX_NAV_SOL_ID:
475  gps_ubx_parse_nav_sol(gubx);
476  break;
477  case UBX_NAV_PVT_ID:
478  gps_ubx_parse_nav_pvt(gubx);
479  break;
480  case UBX_NAV_POSUTM_ID:
482  break;
483  case UBX_NAV_VELECEF_ID:
484  gps_ubx_parse_velecef(gubx);
485  break;
486  case UBX_NAV_VELNED_ID:
488  break;
489  case UBX_NAV_SVINFO_ID:
491  break;
492  case UBX_NAV_SAT_ID:
493  gps_ubx_parse_nav_sat(gubx);
494  break;
495  case UBX_NAV_RELPOSNED_ID:
497  break;
498  default:
499  break;
500  }
501  }
502  else if (gubx->msg_class == UBX_RXM_ID) {
503  switch (gubx->msg_id) {
504  // case UBX_RXM_RTCM_ID:
505  // gps_ubx_parse_rxm_rtcm(gubx);
506  // break;
507  default:
508  break;
509  }
510  }
511 
512 }
513 
514 #if LOG_RAW_GPS
516 #endif
517 
518 /* UBX parsing */
519 void gps_ubx_parse(struct GpsUbx *gubx, uint8_t c)
520 {
521 #if LOG_RAW_GPS
522  sdLogWriteByte(pprzLogFile, c);
523 #endif
524  if (gubx->status < GOT_PAYLOAD) {
525  gubx->ck_a += c;
526  gubx->ck_b += gubx->ck_a;
527  }
528  switch (gubx->status) {
529  case UNINIT:
530  if (c == UBX_SYNC1) {
531  gubx->status++;
532  }
533  break;
534  case GOT_SYNC1:
535  if (c != UBX_SYNC2) {
537  goto error;
538  }
539  gubx->ck_a = 0;
540  gubx->ck_b = 0;
541  gubx->status++;
542  break;
543  case GOT_SYNC2:
544  if (gubx->msg_available) {
545  /* Previous message has not yet been parsed: discard this one */
547  goto error;
548  }
549  gubx->msg_class = c;
550  gubx->status++;
551  break;
552  case GOT_CLASS:
553  gubx->msg_id = c;
554  gubx->status++;
555  break;
556  case GOT_ID:
557  gubx->len = c;
558  gubx->status++;
559  break;
560  case GOT_LEN1:
561  gubx->len |= (c << 8);
562  if (gubx->len > GPS_UBX_MAX_PAYLOAD) {
564  goto error;
565  }
566  gubx->msg_idx = 0;
567  gubx->status++;
568  break;
569  case GOT_LEN2:
570  gubx->msg_buf[gubx->msg_idx] = c;
571  gubx->msg_idx++;
572  if (gubx->msg_idx >= gubx->len) {
573  gubx->status++;
574  }
575  break;
576  case GOT_PAYLOAD:
577  if (c != gubx->ck_a) {
579  goto error;
580  }
581  gubx->status++;
582  break;
583  case GOT_CHECKSUM1:
584  if (c != gubx->ck_b) {
586  goto error;
587  }
588  gubx->msg_available = true;
589  goto restart;
590  break;
591  default:
593  goto error;
594  }
595  return;
596 error:
597  gubx->error_cnt++;
598 restart:
599  gubx->status = UNINIT;
600  return;
601 }
602 
603 static void ubx_send_1byte(struct link_device *dev, uint8_t byte)
604 {
605  dev->put_byte(dev->periph, 0, byte);
606  for(uint8_t i = 0; i < GPS_UBX_NB; i++) {
607  if(gps_ubx[i].dev == dev) {
608  gps_ubx[i].send_ck_a += byte;
610  break;
611  }
612  }
613 }
614 
615 void ubx_header(struct link_device *dev, uint8_t nav_id, uint8_t msg_id, uint16_t len)
616 {
617  dev->put_byte(dev->periph, 0, UBX_SYNC1);
618  dev->put_byte(dev->periph, 0, UBX_SYNC2);
619  for(uint8_t i = 0; i < GPS_UBX_NB; i++) {
620  if(gps_ubx[i].dev == dev) {
621  gps_ubx[i].send_ck_a = 0;
622  gps_ubx[i].send_ck_b = 0;
623  break;
624  }
625  }
626  ubx_send_1byte(dev, nav_id);
627  ubx_send_1byte(dev, msg_id);
628  ubx_send_1byte(dev, (uint8_t)(len & 0xFF));
629  ubx_send_1byte(dev, (uint8_t)(len >> 8));
630 }
631 
632 void ubx_trailer(struct link_device *dev)
633 {
634  for(uint8_t i = 0; i < GPS_UBX_NB; i++) {
635  if(gps_ubx[i].dev == dev) {
636  dev->put_byte(dev->periph, 0, gps_ubx[i].send_ck_a);
637  dev->put_byte(dev->periph, 0, gps_ubx[i].send_ck_b);
638  break;
639  }
640  }
641  dev->send_message(dev->periph, 0);
642 }
643 
644 void ubx_send_bytes(struct link_device *dev, uint8_t len, uint8_t *bytes)
645 {
646  int i;
647  for (i = 0; i < len; i++) {
648  ubx_send_1byte(dev, bytes[i]);
649  }
650 }
651 
652 void ubx_send_cfg_rst(struct link_device *dev, uint16_t bbr , UNUSED uint8_t reset_mode)
653 {
654 #ifdef UBX_GPS_PORT
655  UbxSend_CFG_RST(dev, bbr, reset_mode, 0x00);
656 #endif /* else less harmful for HITL */
657 }
658 
659 #ifndef GPS_UBX_UCENTER
660 #define gps_ubx_ucenter_event() {}
661 #else
663 #endif
664 
665 void gps_ubx_msg(struct GpsUbx *gubx)
666 {
667  // current timestamp
668  uint32_t now_ts = get_sys_time_usec();
669 
672  gps_ubx_read_message(gubx);
674  if (gubx->msg_class == UBX_NAV_ID &&
675  (gubx->msg_id == UBX_NAV_VELNED_ID ||
676  gubx->msg_id == UBX_NAV_PVT_ID ||
677  (gubx->msg_id == UBX_NAV_SOL_ID &&
678  !bit_is_set(gubx->state.valid_fields, GPS_VALID_VEL_NED_BIT)))) {
679  if (gubx->state.fix >= GPS_FIX_3D) {
682 #ifdef GPS_LED
683  LED_ON(GPS_LED);
684  } else {
685  LED_TOGGLE(GPS_LED);
686  }
687 #else
688  }
689 #endif
690  AbiSendMsgGPS(gubx->state.comp_id, now_ts, &gubx->state);
691  }
692  gubx->msg_available = false;
693 }
694 
696 {
697  for(uint8_t i = 0; i < GPS_UBX_NB; i++) {
699  }
700 }
701 
702 /*
703  * Write bytes to the ublox UART connection
704  * This is a wrapper functions used in the librtcm library
705  */
706 void gps_ublox_write(struct link_device *dev, uint8_t *buff, uint32_t n);
707 void gps_ublox_write(struct link_device *dev, uint8_t *buff, uint32_t n)
708 {
709  uint32_t i = 0;
710  for (i = 0; i < n; i++) {
711  dev->put_byte(dev->periph, 0, buff[i]);
712  }
713  dev->send_message(dev->periph, 0);
714  return;
715 }
716 
720 #if USE_GPS_UBX_RTCM
721 void gps_inject_data(uint8_t packet_id, uint8_t length, uint8_t *data)
722 {
723  uint8_t i;
724 
725  // nothing to do
726  if (length == 0) {
727  return;
728  }
729 
730 #ifdef GPS_UBX_UCENTER
731  // not ready
732  if (gps_ubx_ucenter_get_status() != 0) {
733  return;
734  }
735 #endif
736 
737  // go through buffer
738  for (i = 0; i < length; i++) {
739  if (rtcm.nbyte == 0) {
740  // wait for frame start byte
741  if (data[i] == RTCM3_PREAMBLE) {
742  rtcm.buff[rtcm.nbyte++] = data[i];
743  }
744  } else {
745  // fill buffer
746  if (rtcm.nbyte < INJECT_BUFF_SIZE) {
747  rtcm.buff[rtcm.nbyte++] = data[i];
748  if (rtcm.nbyte == 3) {
749  // extract length
750  rtcm.len = RTCMgetbitu(rtcm.buff, 14, 10) + 3;
751  } else {
752  // wait complete frame
753  if (rtcm.nbyte == rtcm.len + 3) {
754  // check CRC
755  unsigned int crc1 = crc24q(rtcm.buff, rtcm.len);
756  unsigned int crc2 = RTCMgetbitu(rtcm.buff, rtcm.len * 8, 24);
757 
758  if (crc1 == crc2) {
759  // write to GPS
760 #ifdef UBX_GPS_PORT
761  gps_ublox_write(&(UBX_GPS_PORT).device, rtcm.buff, rtcm.len + 3);
762 #endif
763  switch (packet_id) {
764  case RTCM3_MSG_1005 : break;
765  case RTCM3_MSG_1077 : break;
766  case RTCM3_MSG_1087 : break;
767  case RTCM3_MSG_4072 : break;
768  case RTCM3_MSG_1230 : break;
769  default: DEBUG_PRINT("Unknown type: %i", packet_id); break;
770  }
771  } else {
772  DEBUG_PRINT("Skipping message %i (CRC failed) - %d", packet_id, rtcm.buff[0]);
773  unsigned int j;
774  for (j = 1; j < rtcm.len; j++) {
775  DEBUG_PRINT(",%d", rtcm.buff[j]);
776  }
777  DEBUG_PRINT("\n");
778  }
779 
780  // reset index
781  rtcm.nbyte = 0;
782  }
783  }
784  } else {
785  // reset index
786  rtcm.nbyte = 0;
787  }
788  }
789  }
790 }
791 
792 #endif /* USE_GPS_UBX_RTCM */
unsigned int RTCMgetbitu(unsigned char *buff, int pos, int lenb)
Definition: CRC24Q.h:54
unsigned int crc24q(const unsigned char *buff, int len)
Definition: CRC24Q.h:44
Main include for ABI (AirBorneInterface).
#define GPS_UBX2_ID
#define GPS_UBX_ID
static uint8_t reset[3]
Definition: baro_MS5534A.c:83
#define LED_ON(i)
Definition: led_hw.h:51
#define LED_TOGGLE(i)
Definition: led_hw.h:53
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:71
uint8_t last_wp UNUSED
#define Min(x, y)
Definition: esc_dshot.c:109
uint16_t gps_week_number(uint16_t year, uint8_t month, uint8_t day)
Number of weeks since navigation epoch (6 January 1980)
Definition: gps.c:649
void WEAK gps_inject_data(uint8_t packet_id, uint8_t length, uint8_t *data)
Default parser for GPS injected data.
Definition: gps.c:418
void gps_periodic_check(struct GpsState *gps_s)
Periodic GPS check.
Definition: gps.c:279
int16_t azim
azimuth in deg
Definition: gps.h:83
uint32_t tow
GPS time of week in ms.
Definition: gps.h:109
float distance_acc
Distance accuracy in meters.
Definition: gps.h:137
uint8_t qi
quality bitfield (GPS receiver specific)
Definition: gps.h:80
int32_t hmsl
height above mean sea level (MSL) in mm
Definition: gps.h:94
int8_t elev
elevation in deg
Definition: gps.h:82
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:92
float heading
Relative heading to the reference station in radians.
Definition: gps.h:134
uint32_t sacc
speed accuracy in cm/s
Definition: gps.h:103
struct UtmCoor_i utm_pos
position in UTM (north,east: cm; alt: mm over MSL)
Definition: gps.h:93
uint32_t cacc
course accuracy in rad*1e7
Definition: gps.h:104
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition: gps.h:99
#define GPS_VALID_VEL_ECEF_BIT
Definition: gps.h:51
#define GPS_VALID_VEL_NED_BIT
Definition: gps.h:52
uint8_t cno
Carrier to Noise Ratio (Signal Strength) in dbHz.
Definition: gps.h:81
float heading_acc
Heading accuracy in radians.
Definition: gps.h:138
struct EcefCoor_i ecef_pos
position in ECEF in cm
Definition: gps.h:91
uint32_t hacc
horizontal accuracy in cm
Definition: gps.h:101
#define GPS_VALID_POS_LLA_BIT
Definition: gps.h:49
double distance
Relative distance to the reference station in meters.
Definition: gps.h:133
uint32_t last_3dfix_ticks
cpu time ticks at last valid 3D fix
Definition: gps.h:114
struct EcefCoor_i ecef_vel
speed ECEF in cm/s
Definition: gps.h:95
#define GPS_NB_CHANNELS
Definition: gps.h:57
uint16_t pdop
position dilution of precision scaled by 100
Definition: gps.h:105
uint32_t tow
Time of week (GPS) in ms.
Definition: gps.h:130
#define GPS_VALID_POS_ECEF_BIT
Definition: gps.h:48
#define GPS_VALID_HMSL_BIT
Definition: gps.h:53
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:96
uint32_t last_msg_time
cpu time in sec at last received GPS message
Definition: gps.h:117
uint8_t svid
Satellite ID.
Definition: gps.h:78
uint8_t nb_channels
Number of scanned satellites.
Definition: gps.h:111
struct NedCoor_f pos_acc
Position accuracy in meters.
Definition: gps.h:136
uint32_t last_3dfix_time
cpu time in sec at last valid 3D fix
Definition: gps.h:115
uint32_t pacc
position accuracy in cm
Definition: gps.h:100
uint16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:97
uint8_t valid_fields
bitfield indicating valid fields (GPS_VALID_x_BIT)
Definition: gps.h:88
uint8_t comp_id
id of current gps
Definition: gps.h:89
uint32_t vacc
vertical accuracy in cm
Definition: gps.h:102
struct NedCoor_d pos
Relative postion to the reference station in meters.
Definition: gps.h:132
#define GPS_FIX_3D
3D GPS fix
Definition: gps.h:44
uint16_t speed_3d
norm of 3d speed in cm/s
Definition: gps.h:98
struct SVinfo svinfos[GPS_NB_CHANNELS]
holds information from the Space Vehicles (Satellites)
Definition: gps.h:112
uint8_t flags
bitfield with GPS receiver specific flags
Definition: gps.h:79
#define GPS_VALID_COURSE_BIT
Definition: gps.h:54
uint32_t last_msg_ticks
cpu time ticks at last received GPS message
Definition: gps.h:116
uint16_t reference_id
Reference station identification.
Definition: gps.h:129
#define GPS_VALID_POS_UTM_BIT
Definition: gps.h:50
uint8_t num_sv
number of sat in fix
Definition: gps.h:106
uint16_t week
GPS week.
Definition: gps.h:108
uint8_t fix
status of fix
Definition: gps.h:107
Definition: gps.h:128
#define GOT_CLASS
Definition: gps_ubx.c:56
#define CFG_RST_BBR_Coldstart
Definition: gps_ubx.c:113
static void gps_ubx_parse_nav_sat(struct GpsUbx *gubx)
Definition: gps_ubx.c:377
void gps_ubx_periodic_check(void)
Definition: gps_ubx.c:695
void ubx_trailer(struct link_device *dev)
Definition: gps_ubx.c:632
void gps_ubx_parse_HITL_UBX(uint8_t *buf)
Definition: gps_ubx.c:164
void ubx_header(struct link_device *dev, uint8_t nav_id, uint8_t msg_id, uint16_t len)
Definition: gps_ubx.c:615
#define GPS_UBX_ERR_UNEXPECTED
Definition: gps_ubx.c:70
void gps_ubx_read_message(struct GpsUbx *gubx)
Definition: gps_ubx.c:460
#define GPS_UBX_ERR_OVERRUN
Definition: gps_ubx.c:67
#define UTM_HEM_SOUTH
Definition: gps_ubx.c:74
#define GPS_UBX_BOOTRESET
Definition: gps_ubx.c:102
static void gps_ubx_parse_nav_posecef(struct GpsUbx *gubx)
Definition: gps_ubx.c:275
#define GOT_SYNC2
Definition: gps_ubx.c:55
#define NAV_RELPOSNED_VERSION
Definition: gps_ubx.c:64
static void ubx_send_1byte(struct link_device *dev, uint8_t byte)
Definition: gps_ubx.c:603
static void gps_ubx_parse_nav_pvt(struct GpsUbx *gubx)
Definition: gps_ubx.c:180
#define GPS_UBX_ERR_NONE
Definition: gps_ubx.c:66
static void gps_ubx_parse_nav_posutm(struct GpsUbx *gubx)
Definition: gps_ubx.c:307
#define GOT_LEN1
Definition: gps_ubx.c:58
void gps_ublox_write(struct link_device *dev, uint8_t *buff, uint32_t n)
Definition: gps_ubx.c:707
#define GPS_UBX_ERR_MSG_TOO_LONG
Definition: gps_ubx.c:68
#define GOT_PAYLOAD
Definition: gps_ubx.c:60
#define GOT_SYNC1
Definition: gps_ubx.c:54
#define UNINIT
Includes macros generated from ubx.xml.
Definition: gps_ubx.c:53
#define GOT_CHECKSUM1
Definition: gps_ubx.c:61
#define CFG_RST_Reset_Controlled
Definition: gps_ubx.c:106
#define CFG_RST_BBR_Hotstart
Definition: gps_ubx.c:111
void gps_ubx_event(void)
Definition: gps_ubx.c:137
#define GOT_ID
Definition: gps_ubx.c:57
#define DEBUG_PRINT(...)
Definition: gps_ubx.c:46
#define GPS_UBX_ERR_CHECKSUM
Definition: gps_ubx.c:69
void ubx_send_cfg_rst(struct link_device *dev, uint16_t bbr, UNUSED uint8_t reset_mode)
Definition: gps_ubx.c:652
static void gps_ubx_parse_nav_sol(struct GpsUbx *gubx)
Definition: gps_ubx.c:243
void gps_ubx_msg(struct GpsUbx *gubx)
Definition: gps_ubx.c:665
uint8_t gps_ubx_reset
Definition: gps_ubx.c:77
struct GpsUbx gps_ubx[GPS_UBX_NB]
Definition: gps_ubx.c:76
#define gps_ubx_ucenter_event()
Definition: gps_ubx.c:660
void gps_ubx_init(void)
Definition: gps_ubx.c:115
static void gps_ubx_parse_nav_posllh(struct GpsUbx *gubx)
Definition: gps_ubx.c:290
#define CFG_RST_BBR_Warmstart
Definition: gps_ubx.c:112
static void gps_ubx_parse_nav_velned(struct GpsUbx *gubx)
Definition: gps_ubx.c:340
static void gps_ubx_parse_velecef(struct GpsUbx *gubx)
Definition: gps_ubx.c:326
static void gps_ubx_parse_nav_svinfo(struct GpsUbx *gubx)
Definition: gps_ubx.c:361
void gps_ubx_parse(struct GpsUbx *gubx, uint8_t c)
Definition: gps_ubx.c:519
void ubx_send_bytes(struct link_device *dev, uint8_t len, uint8_t *bytes)
Definition: gps_ubx.c:644
static void gps_ubx_parse_nav_status(struct GpsUbx *gubx)
Definition: gps_ubx.c:401
static void gps_ubx_parse_nav_relposned(struct GpsUbx *gubx)
Definition: gps_ubx.c:413
#define GOT_LEN2
Definition: gps_ubx.c:59
#define GPS_UBX_ERR_OUT_OF_SYNC
Definition: gps_ubx.c:71
UBX protocol specific code.
uint16_t len
Definition: gps_ubx.h:61
uint8_t ck_b
Definition: gps_ubx.h:63
struct GpsState state
Definition: gps_ubx.h:72
uint8_t status_flags
Definition: gps_ubx.h:68
uint8_t status
Definition: gps_ubx.h:60
#define GPS_UBX_NB
Definition: gps_ubx.h:39
uint8_t msg_class
Definition: gps_ubx.h:58
struct link_device * dev
Definition: gps_ubx.h:54
uint8_t msg_buf[GPS_UBX_MAX_PAYLOAD]
Definition: gps_ubx.h:56
uint8_t error_cnt
Definition: gps_ubx.h:65
bool pacc_valid
Definition: gps_ubx.h:70
uint8_t send_ck_b
Definition: gps_ubx.h:64
uint8_t send_ck_a
Definition: gps_ubx.h:64
uint8_t msg_id
Definition: gps_ubx.h:57
uint8_t error_last
Definition: gps_ubx.h:66
#define GPS_UBX_MAX_PAYLOAD
Definition: gps_ubx.h:51
bool msg_available
Definition: gps_ubx.h:55
uint8_t ck_a
Definition: gps_ubx.h:63
uint16_t msg_idx
Definition: gps_ubx.h:62
Definition: gps_ubx.h:53
int gps_ubx_ucenter_get_status(void)
Configure Ublox GPS.
double y
in meters
double z
in meters
double x
in meters
int32_t lat
in degrees*1e7
int32_t alt
in millimeters (above WGS84 reference ellipsoid or above MSL)
int32_t alt
in millimeters above WGS84 reference ellipsoid
int32_t z
Down.
int32_t z
in centimeters
uint8_t zone
UTM zone number.
int32_t x
in centimeters
int32_t y
East.
int32_t east
in centimeters
int32_t y
in centimeters
int32_t lon
in degrees*1e7
int32_t x
North.
int32_t north
in centimeters
struct State state
Definition: state.c:36
uint8_t buff[25]
Buffer used for general comunication over SPI (in buffer)
arch independent LED (Light Emitting Diodes) API
#define byte
float z
in meters
float x
in meters
float y
in meters
#define RTCM3_MSG_1005
Definition: rtcm3.h:20
#define RTCM3_MSG_1077
Definition: rtcm3.h:22
#define RTCM3_MSG_4072
Definition: rtcm3.h:21
#define RTCM3_MSG_1230
Definition: rtcm3.h:24
#define RTCM3_MSG_1087
Definition: rtcm3.h:23
#define RTCM3_PREAMBLE
Definition: rtcm3.h:19
FileDes pprzLogFile
Definition: sdlog_chibios.c:75
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
volatile uint32_t nb_sec
full seconds since startup
Definition: sys_time.h:72
volatile uint32_t nb_sec_rem
remainder of seconds since startup in CPU_TICKS
Definition: sys_time.h:73
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98