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