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