Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
gps_ubx.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 Antoine Drouin <poinix@gmail.com>
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22
23#include "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
78void gps_ubx_parse(struct GpsUbx *gubx, uint8_t c);
79void gps_ubx_msg(struct GpsUbx *gubx);
80
81#if USE_GPS_UBX_RTCM
82extern 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 */
89struct rtcm_t {
91 uint32_t len;
93};
94struct 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
115void 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
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 {
172 gps_ubx[0].msg_id = DL_HITL_UBX_id(buf);
175 memcpy(gps_ubx[0].msg_buf, ubx_payload, l);
176 gps_ubx[0].msg_available = true;
177 }
178}
179
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);
210 SetBit(gubx->state.valid_fields, GPS_VALID_POS_LLA_BIT);
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;
229 SetBit(gubx->state.valid_fields, GPS_VALID_VEL_NED_BIT);
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
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);
260 SetBit(gubx->state.valid_fields, GPS_VALID_POS_ECEF_BIT);
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);
266 SetBit(gubx->state.valid_fields, GPS_VALID_VEL_ECEF_BIT);
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
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);
283 SetBit(gubx->state.valid_fields, GPS_VALID_POS_ECEF_BIT);
284
285 // Copy accuracy information
286 gubx->state.pacc = UBX_NAV_POSECEF_pAcc(gubx->msg_buf);
287 gubx->pacc_valid = true;
288}
289
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);
296 SetBit(gubx->state.valid_fields, GPS_VALID_POS_LLA_BIT);
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
308{
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);
319 SetBit(gubx->state.valid_fields, GPS_VALID_POS_UTM_BIT);
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
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);
334 SetBit(gubx->state.valid_fields, GPS_VALID_VEL_ECEF_BIT);
335
336 // Copy accuracy measurements
337 gubx->state.sacc = UBX_NAV_VELECEF_sAcc(gubx->msg_buf);
338}
339
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);
350 SetBit(gubx->state.valid_fields, GPS_VALID_VEL_NED_BIT);
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
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
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
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
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
437 struct RelPosNED relpos = {0};
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
459void gps_ubx_read_message(struct GpsUbx *gubx);
461{
462
463 if (gubx->msg_class == UBX_NAV_ID) {
464 switch (gubx->msg_id) {
467 break;
470 break;
473 break;
474 case UBX_NAV_SOL_ID:
476 break;
477 case UBX_NAV_PVT_ID:
479 break;
482 break;
485 break;
488 break;
491 break;
492 case UBX_NAV_SAT_ID:
494 break;
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 */
520{
521#if LOG_RAW_GPS
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) {
536 gubx->error_last = GPS_UBX_ERR_OUT_OF_SYNC;
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 */
546 gubx->error_last = GPS_UBX_ERR_OVERRUN;
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) {
563 gubx->error_last = GPS_UBX_ERR_MSG_TOO_LONG;
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) {
578 gubx->error_last = GPS_UBX_ERR_CHECKSUM;
579 goto error;
580 }
581 gubx->status++;
582 break;
583 case GOT_CHECKSUM1:
584 if (c != gubx->ck_b) {
585 gubx->error_last = GPS_UBX_ERR_CHECKSUM;
586 goto error;
587 }
588 gubx->msg_available = true;
589 goto restart;
590 break;
591 default:
592 gubx->error_last = GPS_UBX_ERR_UNEXPECTED;
593 goto error;
594 }
595 return;
596error:
597 gubx->error_cnt++;
598restart:
599 gubx->status = UNINIT;
600 return;
601}
602
603static 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
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 }
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
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
644void 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
653{
654#ifdef UBX_GPS_PORT
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
666{
667 // current timestamp
669
670 gubx->state.last_msg_ticks = sys_time.nb_sec_rem;
671 gubx->state.last_msg_time = sys_time.nb_sec;
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) {
680 gubx->state.last_3dfix_ticks = sys_time.nb_sec_rem;
681 gubx->state.last_3dfix_time = sys_time.nb_sec;
682#ifdef GPS_LED
684 } else {
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 */
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
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]
#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.
#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
#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_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:89
#define GPS_FIX_3D
3D GPS fix
Definition gps.h:44
#define GPS_VALID_COURSE_BIT
Definition gps.h:54
uint16_t reference_id
Reference station identification.
Definition gps.h:129
#define GPS_VALID_POS_UTM_BIT
Definition gps.h:50
#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.
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:24
#define RTCM3_MSG_1087
Definition rtcm3.h:23
#define RTCM3_PREAMBLE
Definition rtcm3.h:19
FileDes pprzLogFile
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.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.