PX4 Firmware
PX4 Autopilot Software http://px4.io
ubx.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file ubx.cpp
36  *
37  * U-Blox protocol implementation. Following u-blox 6/7/8/9 Receiver Description
38  * including Prototol Specification.
39  *
40  * @author Thomas Gubler <thomasgubler@student.ethz.ch>
41  * @author Julian Oes <julian@oes.ch>
42  * @author Anton Babushkin <anton.babushkin@me.com>
43  * @author Beat Kueng <beat-kueng@gmx.net>
44  *
45  * @author Hannes Delago
46  * (rework, add ubx7+ compatibility)
47  *
48  * @see https://www2.u-blox.com/images/downloads/Product_Docs/u-blox6-GPS-GLONASS-QZSS-V14_ReceiverDescriptionProtocolSpec_Public_(GPS.G6-SW-12013).pdf
49  * @see https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_%28UBX-13003221%29_Public.pdf
50  * @see https://www.u-blox.com/sites/default/files/u-blox_ZED-F9P_InterfaceDescription_%28UBX-18010854%29.pdf
51  */
52 
53 #include <assert.h>
54 #include <math.h>
55 #include <stdio.h>
56 #include <string.h>
57 #include <ctime>
58 
59 #include "ubx.h"
60 #include "rtcm.h"
61 
62 #define UBX_CONFIG_TIMEOUT 250 // ms, timeout for waiting ACK
63 #define UBX_PACKET_TIMEOUT 2 // ms, if now data during this delay assume that full update received
64 #define DISABLE_MSG_INTERVAL 1000000 // us, try to disable message with this interval
65 
66 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
67 #define SWAP16(X) ((((X) >> 8) & 0x00ff) | (((X) << 8) & 0xff00))
68 
69 #define FNV1_32_INIT ((uint32_t)0x811c9dc5) // init value for FNV1 hash algorithm
70 #define FNV1_32_PRIME ((uint32_t)0x01000193) // magic prime for FNV1 hash algorithm
71 
72 
73 /**** Trace macros, disable for production builds */
74 #define UBX_TRACE_PARSER(...) {/*GPS_INFO(__VA_ARGS__);*/} /* decoding progress in parse_char() */
75 #define UBX_TRACE_RXMSG(...) {/*GPS_INFO(__VA_ARGS__);*/} /* Rx msgs in payload_rx_done() */
76 #define UBX_TRACE_SVINFO(...) {/*GPS_INFO(__VA_ARGS__);*/} /* NAV-SVINFO processing (debug use only, will cause rx buffer overflows) */
77 
78 /**** Warning macros, disable to save memory */
79 #define UBX_WARN(...) {GPS_WARN(__VA_ARGS__);}
80 #define UBX_DEBUG(...) {/*GPS_WARN(__VA_ARGS__);*/}
81 
82 GPSDriverUBX::GPSDriverUBX(Interface gpsInterface, GPSCallbackPtr callback, void *callback_user,
83  struct vehicle_gps_position_s *gps_position,
84  struct satellite_info_s *satellite_info,
85  uint8_t dynamic_model)
86  : GPSBaseStationSupport(callback, callback_user)
87  , _gps_position(gps_position)
88  , _satellite_info(satellite_info)
89  , _interface(gpsInterface)
90  , _dyn_model(dynamic_model)
91 {
92  decodeInit();
93 }
94 
96 {
97  if (_rtcm_parsing) {
98  delete (_rtcm_parsing);
99  }
100 }
101 
102 int
104 {
105  _configured = false;
106  _output_mode = output_mode;
107 
108  ubx_payload_tx_cfg_prt_t cfg_prt[2];
109  uint16_t out_proto_mask = output_mode == OutputMode::GPS ?
112  uint16_t in_proto_mask = output_mode == OutputMode::GPS ?
115  const bool auto_baudrate = baudrate == 0;
116 
117  if (_interface == Interface::UART) {
118 
119  /* try different baudrates */
120  const unsigned baudrates[] = {38400, 57600, 9600, 115200, 230400};
121 
122  unsigned baud_i;
123  unsigned desired_baudrate = auto_baudrate ? UBX_BAUDRATE_M8_AND_NEWER : baudrate;
124 
125  for (baud_i = 0; baud_i < sizeof(baudrates) / sizeof(baudrates[0]); baud_i++) {
126  unsigned test_baudrate = baudrates[baud_i];
127 
128  if (!auto_baudrate && baudrate != test_baudrate) {
129  continue; // skip to next baudrate
130  }
131 
132  UBX_DEBUG("baudrate set to %i", test_baudrate);
133 
134  setBaudrate(test_baudrate);
135 
136  /* flush input and wait for at least 20 ms silence */
137  decodeInit();
138  receive(20);
139  decodeInit();
140 
141  // try CFG-VALSET: if we get an ACK we know we can use protocol version 27+
142  int cfg_valset_msg_size = initCfgValset();
143  // UART1
144  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1_STOPBITS, 1, cfg_valset_msg_size);
145  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1_DATABITS, 0, cfg_valset_msg_size);
146  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1_PARITY, 0, cfg_valset_msg_size);
147  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1INPROT_UBX, 1, cfg_valset_msg_size);
148  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1INPROT_RTCM3X, output_mode == OutputMode::GPS ? 1 : 0,
149  cfg_valset_msg_size);
150  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1INPROT_NMEA, 0, cfg_valset_msg_size);
151  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1OUTPROT_UBX, 1, cfg_valset_msg_size);
152  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1OUTPROT_RTCM3X, output_mode == OutputMode::GPS ? 0 : 1,
153  cfg_valset_msg_size);
154  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_UART1OUTPROT_NMEA, 0, cfg_valset_msg_size);
155  // TODO: are we ever connected to UART2?
156 
157  // USB
158  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_USBINPROT_UBX, 1, cfg_valset_msg_size);
159  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_USBINPROT_RTCM3X, output_mode == OutputMode::GPS ? 1 : 0,
160  cfg_valset_msg_size);
161  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_USBINPROT_NMEA, 0, cfg_valset_msg_size);
162  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_USBOUTPROT_UBX, 1, cfg_valset_msg_size);
163  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_USBOUTPROT_RTCM3X, output_mode == OutputMode::GPS ? 0 : 1,
164  cfg_valset_msg_size);
165  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_USBOUTPROT_NMEA, 0, cfg_valset_msg_size);
166 
167  bool cfg_valset_success = false;
168 
169  if (sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
170 
172  cfg_valset_success = true;
173  }
174  }
175 
176  if (cfg_valset_success) {
178  // Now we only have to change the baudrate
179  cfg_valset_msg_size = initCfgValset();
180  cfgValset<uint32_t>(UBX_CFG_KEY_CFG_UART1_BAUDRATE, desired_baudrate, cfg_valset_msg_size);
181 
182  if (!sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
183  continue;
184  }
185 
186  /* no ACK is expected here, but read the buffer anyway in case we actually get an ACK */
188 
189  } else {
190  _proto_ver_27_or_higher = false;
191 
192  if (auto_baudrate) {
193  desired_baudrate = UBX_TX_CFG_PRT_BAUDRATE;
194  }
195 
196  UBX_DEBUG("trying old protocol");
197 
198  /* Send a CFG-PRT message to set the UBX protocol for in and out
199  * and leave the baudrate as it is, we just want an ACK-ACK for this */
200  memset(cfg_prt, 0, 2 * sizeof(ubx_payload_tx_cfg_prt_t));
201  cfg_prt[0].portID = UBX_TX_CFG_PRT_PORTID;
202  cfg_prt[0].mode = UBX_TX_CFG_PRT_MODE;
203  cfg_prt[0].baudRate = test_baudrate;
204  cfg_prt[0].inProtoMask = in_proto_mask;
205  cfg_prt[0].outProtoMask = out_proto_mask;
206  cfg_prt[1].portID = UBX_TX_CFG_PRT_PORTID_USB;
207  cfg_prt[1].mode = UBX_TX_CFG_PRT_MODE;
208  cfg_prt[1].baudRate = test_baudrate;
209  cfg_prt[1].inProtoMask = in_proto_mask;
210  cfg_prt[1].outProtoMask = out_proto_mask;
211 
212  if (!sendMessage(UBX_MSG_CFG_PRT, (uint8_t *)cfg_prt, 2 * sizeof(ubx_payload_tx_cfg_prt_t))) {
213  continue;
214  }
215 
216  if (waitForAck(UBX_MSG_CFG_PRT, UBX_CONFIG_TIMEOUT, false) < 0) {
217  /* try next baudrate */
218  continue;
219  }
220 
221  /* Send a CFG-PRT message again, this time change the baudrate */
222  cfg_prt[0].baudRate = desired_baudrate;
223  cfg_prt[1].baudRate = desired_baudrate;
224 
225  if (!sendMessage(UBX_MSG_CFG_PRT, (uint8_t *)cfg_prt, 2 * sizeof(ubx_payload_tx_cfg_prt_t))) {
226  continue;
227  }
228 
229  /* no ACK is expected here, but read the buffer anyway in case we actually get an ACK */
231  }
232 
233  if (desired_baudrate != test_baudrate) {
234  setBaudrate(desired_baudrate);
235 
236  decodeInit();
237  receive(20);
238  decodeInit();
239  }
240 
241  /* at this point we have correct baudrate on both ends */
242  baudrate = desired_baudrate;
243  break;
244  }
245 
246  if (baud_i >= sizeof(baudrates) / sizeof(baudrates[0])) {
247  return -1; // connection and/or baudrate detection failed
248  }
249 
250  } else if (_interface == Interface::SPI) {
251 
252  // try CFG-VALSET: if we get an ACK we know we can use protocol version 27+
253  int cfg_valset_msg_size = initCfgValset();
254  cfgValset<uint8_t>(UBX_CFG_KEY_SPI_ENABLED, 1, cfg_valset_msg_size);
255  cfgValset<uint8_t>(UBX_CFG_KEY_SPI_MAXFF, 1, cfg_valset_msg_size);
256  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_SPIINPROT_UBX, 1, cfg_valset_msg_size);
257  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_SPIINPROT_RTCM3X, output_mode == OutputMode::GPS ? 1 : 0, cfg_valset_msg_size);
258  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_SPIINPROT_NMEA, 0, cfg_valset_msg_size);
259  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_SPIOUTPROT_UBX, 1, cfg_valset_msg_size);
260  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_SPIOUTPROT_RTCM3X, output_mode == OutputMode::GPS ? 0 : 1, cfg_valset_msg_size);
261  cfgValset<uint8_t>(UBX_CFG_KEY_CFG_SPIOUTPROT_NMEA, 0, cfg_valset_msg_size);
262 
263  bool cfg_valset_success = false;
264 
265  if (sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
266 
268  cfg_valset_success = true;
269  }
270  }
271 
272  if (cfg_valset_success) {
274 
275  } else {
276  _proto_ver_27_or_higher = false;
277  memset(cfg_prt, 0, sizeof(ubx_payload_tx_cfg_prt_t));
278  cfg_prt[0].portID = UBX_TX_CFG_PRT_PORTID_SPI;
279  cfg_prt[0].mode = UBX_TX_CFG_PRT_MODE_SPI;
280  cfg_prt[0].inProtoMask = in_proto_mask;
281  cfg_prt[0].outProtoMask = out_proto_mask;
282 
283  if (!sendMessage(UBX_MSG_CFG_PRT, (uint8_t *)cfg_prt, sizeof(ubx_payload_tx_cfg_prt_t))) {
284  return -1;
285  }
286 
288  }
289 
290  } else {
291  return -1;
292  }
293 
294  UBX_DEBUG("Protocol version 27+: %i", (int)_proto_ver_27_or_higher);
295 
296  /* Request module version information by sending an empty MON-VER message */
297  if (!sendMessage(UBX_MSG_MON_VER, nullptr, 0)) {
298  return -1;
299  }
300 
301  /* Wait for the reply so that we know to which device we're connected (_board will be set).
302  * Note: we won't actually get an ACK-ACK, but UBX_MSG_MON_VER will also set the ack state.
303  */
305  return -1;
306  }
307 
308 
309  /* Now that we know the board, update the baudrate on M8 boards (on F9+ we already used the
310  * higher baudrate with CFG-VALSET) */
311  if (_interface == Interface::UART && auto_baudrate && _board == Board::u_blox8) {
312 
313  cfg_prt[0].baudRate = UBX_BAUDRATE_M8_AND_NEWER;
314  cfg_prt[1].baudRate = UBX_BAUDRATE_M8_AND_NEWER;
315 
316  if (sendMessage(UBX_MSG_CFG_PRT, (uint8_t *)cfg_prt, 2 * sizeof(ubx_payload_tx_cfg_prt_t))) {
317  /* no ACK is expected here, but read the buffer anyway in case we actually get an ACK */
319 
321  baudrate = UBX_BAUDRATE_M8_AND_NEWER;
322  }
323  }
324 
325 
326  if (output_mode != OutputMode::GPS) {
327  // RTCM mode force stationary dynamic model
328  _dyn_model = 2;
329  }
330 
331  int ret;
332 
333  if (_proto_ver_27_or_higher) {
334  ret = configureDevice();
335 
336  } else {
337  ret = configureDevicePreV27();
338  }
339 
340  if (ret != 0) {
341  return ret;
342  }
343 
344  if (output_mode == OutputMode::RTCM) {
345  if (restartSurveyIn() < 0) {
346  return -1;
347  }
348  }
349 
350  _configured = true;
351  return 0;
352 }
353 
354 
356 {
357  /* Send a CFG-RATE message to define update rate */
358  memset(&_buf.payload_tx_cfg_rate, 0, sizeof(_buf.payload_tx_cfg_rate));
362 
363  if (!sendMessage(UBX_MSG_CFG_RATE, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_rate))) {
364  return -1;
365  }
366 
368  return -1;
369  }
370 
371  /* send a NAV5 message to set the options for the internal filter */
372  memset(&_buf.payload_tx_cfg_nav5, 0, sizeof(_buf.payload_tx_cfg_nav5));
373  _buf.payload_tx_cfg_nav5.mask = UBX_TX_CFG_NAV5_MASK;
374  _buf.payload_tx_cfg_nav5.dynModel = _dyn_model;
375  _buf.payload_tx_cfg_nav5.fixMode = UBX_TX_CFG_NAV5_FIXMODE;
376 
377  if (!sendMessage(UBX_MSG_CFG_NAV5, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_nav5))) {
378  return -1;
379  }
380 
382  return -1;
383  }
384 
385  /* configure message rates */
386  /* the last argument is divisor for measurement rate (set by CFG RATE), i.e. 1 means 5Hz */
387 
388  /* try to set rate for NAV-PVT */
389  /* (implemented for ubx7+ modules only, use NAV-SOL, NAV-POSLLH, NAV-VELNED and NAV-TIMEUTC for ubx6) */
391  return -1;
392  }
393 
395  _use_nav_pvt = false;
396 
397  } else {
398  _use_nav_pvt = true;
399  }
400 
401  UBX_DEBUG("%susing NAV-PVT", _use_nav_pvt ? "" : "not ");
402 
403  if (!_use_nav_pvt) {
405  return -1;
406  }
407 
409  return -1;
410  }
411 
413  return -1;
414  }
415 
417  return -1;
418  }
419  }
420 
422  return -1;
423  }
424 
425  if (!configureMessageRateAndAck(UBX_MSG_NAV_SVINFO, (_satellite_info != nullptr) ? 5 : 0, true)) {
426  return -1;
427  }
428 
430  return -1;
431  }
432 
433  return 0;
434 }
435 
437 {
438  /* set configuration parameters */
439  int cfg_valset_msg_size = initCfgValset();
440  cfgValset<uint8_t>(UBX_CFG_KEY_NAVHPG_DGNSSMODE, 3 /* RTK Fixed */, cfg_valset_msg_size);
441  cfgValset<uint8_t>(UBX_CFG_KEY_NAVSPG_FIXMODE, 3 /* Auto 2d/3d */, cfg_valset_msg_size);
442  cfgValset<uint8_t>(UBX_CFG_KEY_NAVSPG_UTCSTANDARD, 3 /* USNO (U.S. Naval Observatory derived from GPS) */,
443  cfg_valset_msg_size);
444  cfgValset<uint8_t>(UBX_CFG_KEY_NAVSPG_DYNMODEL, _dyn_model, cfg_valset_msg_size);
445 
446  // disable odometer & filtering
447  cfgValset<uint8_t>(UBX_CFG_KEY_ODO_USE_ODO, 0, cfg_valset_msg_size);
448  cfgValset<uint8_t>(UBX_CFG_KEY_ODO_USE_COG, 0, cfg_valset_msg_size);
449  cfgValset<uint8_t>(UBX_CFG_KEY_ODO_OUTLPVEL, 0, cfg_valset_msg_size);
450  cfgValset<uint8_t>(UBX_CFG_KEY_ODO_OUTLPCOG, 0, cfg_valset_msg_size);
451 
452  // measurement rate
453  cfgValset<uint16_t>(UBX_CFG_KEY_RATE_MEAS, 100 /* 10 Hz update rate */, cfg_valset_msg_size);
454  cfgValset<uint16_t>(UBX_CFG_KEY_RATE_NAV, 1, cfg_valset_msg_size);
455  cfgValset<uint8_t>(UBX_CFG_KEY_RATE_TIMEREF, 0, cfg_valset_msg_size);
456 
457  if (!sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
458  return -1;
459  }
460 
462  return -1;
463  }
464 
465  // Configure message rates
466  // Send a new CFG-VALSET message to make sure it does not get too large
467  cfg_valset_msg_size = initCfgValset();
468  cfgValsetPort(UBX_CFG_KEY_MSGOUT_UBX_NAV_PVT_I2C, 1, cfg_valset_msg_size);
469  _use_nav_pvt = true;
470  cfgValsetPort(UBX_CFG_KEY_MSGOUT_UBX_NAV_DOP_I2C, 1, cfg_valset_msg_size);
471  cfgValsetPort(UBX_CFG_KEY_MSGOUT_UBX_NAV_SAT_I2C, (_satellite_info != nullptr) ? 10 : 0, cfg_valset_msg_size);
472  cfgValsetPort(UBX_CFG_KEY_MSGOUT_UBX_MON_RF_I2C, 1, cfg_valset_msg_size);
473 
474  if (!sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
475  return -1;
476  }
477 
479  return -1;
480  }
481 
482  return 0;
483 }
484 
486 {
490 }
491 
492 template<typename T>
493 bool GPSDriverUBX::cfgValset(uint32_t key_id, T value, int &msg_size)
494 {
495  if (msg_size + sizeof(key_id) + sizeof(value) > sizeof(_buf)) {
496  // If this happens use several CFG-VALSET messages instead of one
497  UBX_WARN("buf for CFG_VALSET too small");
498  return false;
499  }
500 
501  uint8_t *buffer = (uint8_t *)&_buf.payload_tx_cfg_valset;
502  memcpy(buffer + msg_size, &key_id, sizeof(key_id));
503  msg_size += sizeof(key_id);
504  memcpy(buffer + msg_size, &value, sizeof(value));
505  msg_size += sizeof(value);
506  return true;
507 }
508 
509 bool GPSDriverUBX::cfgValsetPort(uint32_t key_id, uint8_t value, int &msg_size)
510 {
511  if (_interface == Interface::SPI) {
512  if (!cfgValset<uint8_t>(key_id + 4, value, msg_size)) {
513  return false;
514  }
515 
516  } else {
517  // enable on UART1 & USB (TODO: should we enable UART2 too? -> better would be to detect the port)
518  if (!cfgValset<uint8_t>(key_id + 1, value, msg_size)) {
519  return false;
520  }
521 
522  if (!cfgValset<uint8_t>(key_id + 3, value, msg_size)) {
523  return false;
524  }
525  }
526 
527  return true;
528 }
529 
531 {
532  //disable RTCM output
539 
540  //stop it first
541  //FIXME: stopping the survey-in process does not seem to work
543  _buf.payload_tx_cfg_tmode3.flags = 0; /* disable time mode */
544 
545  if (!sendMessage(UBX_MSG_CFG_TMODE3, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_tmode3))) {
546  UBX_WARN("TMODE3 failed. Device w/o base station support?");
547  return -1;
548  }
549 
551  return -1;
552  }
553 
555  UBX_DEBUG("Starting Survey-in");
556 
557  memset(&_buf.payload_tx_cfg_tmode3, 0, sizeof(_buf.payload_tx_cfg_tmode3));
558  _buf.payload_tx_cfg_tmode3.flags = 1; /* start survey-in */
559  _buf.payload_tx_cfg_tmode3.svinMinDur = _base_settings.settings.survey_in.min_dur;
560  _buf.payload_tx_cfg_tmode3.svinAccLimit = _base_settings.settings.survey_in.acc_limit;
561 
562  if (!sendMessage(UBX_MSG_CFG_TMODE3, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_tmode3))) {
563  return -1;
564  }
565 
567  return -1;
568  }
569 
570  /* enable status output of survey-in */
572  return -1;
573  }
574 
575  } else {
576  UBX_DEBUG("Setting fixed base position");
577 
579 
580  memset(&_buf.payload_tx_cfg_tmode3, 0, sizeof(_buf.payload_tx_cfg_tmode3));
581  _buf.payload_tx_cfg_tmode3.flags = 2 /* fixed mode */ | (1 << 8) /* lat/lon mode */;
582  int64_t lat64 = (int64_t)(settings.latitude * 1e9);
583  _buf.payload_tx_cfg_tmode3.ecefXOrLat = (int32_t)(lat64 / 100);
584  _buf.payload_tx_cfg_tmode3.ecefXOrLatHP = lat64 % 100; // range [-99, 99]
585  int64_t lon64 = (int64_t)(settings.longitude * 1e9);
586  _buf.payload_tx_cfg_tmode3.ecefYOrLon = (int32_t)(lon64 / 100);
587  _buf.payload_tx_cfg_tmode3.ecefYOrLonHP = lon64 % 100;
588  int64_t alt64 = (int64_t)((double)settings.altitude * 1e4);
589  _buf.payload_tx_cfg_tmode3.ecefZOrAlt = (int32_t)(alt64 / 100); // cm
590  _buf.payload_tx_cfg_tmode3.ecefZOrAltHP = alt64 % 100; // 0.1mm
591 
592  _buf.payload_tx_cfg_tmode3.fixedPosAcc = (uint32_t)(settings.position_accuracy * 10.f);
593 
594  if (!sendMessage(UBX_MSG_CFG_TMODE3, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_tmode3))) {
595  return -1;
596  }
597 
599  return -1;
600  }
601 
602  // directly enable RTCM3 output
603  return activateRTCMOutput();
604  }
605 
606  return 0;
607 }
608 
610 {
612  return -1;
613  }
614 
616  return restartSurveyInPreV27();
617  }
618 
619  //disable RTCM output
620  int cfg_valset_msg_size = initCfgValset();
627  sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size);
629 
631  UBX_DEBUG("Starting Survey-in");
632 
633  cfg_valset_msg_size = initCfgValset();
634  cfgValset<uint8_t>(UBX_CFG_KEY_TMODE_MODE, 1 /* Survey-in */, cfg_valset_msg_size);
635  cfgValset<uint32_t>(UBX_CFG_KEY_TMODE_SVIN_MIN_DUR, _base_settings.settings.survey_in.min_dur, cfg_valset_msg_size);
636  cfgValset<uint32_t>(UBX_CFG_KEY_TMODE_SVIN_ACC_LIMIT, _base_settings.settings.survey_in.acc_limit, cfg_valset_msg_size);
637  cfgValsetPort(UBX_CFG_KEY_MSGOUT_UBX_NAV_SVIN_I2C, 5, cfg_valset_msg_size);
638 
639  if (!sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
640  return -1;
641  }
642 
644  return -1;
645  }
646 
647  } else {
648  UBX_DEBUG("Setting fixed base position");
649 
651  cfg_valset_msg_size = initCfgValset();
652  cfgValset<uint8_t>(UBX_CFG_KEY_TMODE_MODE, 2 /* Fixed Mode */, cfg_valset_msg_size);
653  cfgValset<uint8_t>(UBX_CFG_KEY_TMODE_POS_TYPE, 1 /* Lat/Lon/Height */, cfg_valset_msg_size);
654  int64_t lat64 = (int64_t)(settings.latitude * 1e9);
655  cfgValset<int32_t>(UBX_CFG_KEY_TMODE_LAT, (int32_t)(lat64 / 100), cfg_valset_msg_size);
656  cfgValset<int8_t>(UBX_CFG_KEY_TMODE_LAT_HP, lat64 % 100 /* range [-99, 99] */, cfg_valset_msg_size);
657  int64_t lon64 = (int64_t)(settings.longitude * 1e9);
658  cfgValset<int32_t>(UBX_CFG_KEY_TMODE_LON, (int32_t)(lon64 / 100), cfg_valset_msg_size);
659  cfgValset<int8_t>(UBX_CFG_KEY_TMODE_LON_HP, lon64 % 100 /* range [-99, 99] */, cfg_valset_msg_size);
660  int64_t alt64 = (int64_t)((double)settings.altitude * 1e4);
661  cfgValset<int32_t>(UBX_CFG_KEY_TMODE_HEIGHT, (int32_t)(alt64 / 100) /* cm */, cfg_valset_msg_size);
662  cfgValset<int8_t>(UBX_CFG_KEY_TMODE_HEIGHT_HP, alt64 % 100 /* 0.1mm */, cfg_valset_msg_size);
663  cfgValset<uint32_t>(UBX_CFG_KEY_TMODE_FIXED_POS_ACC, (uint32_t)(settings.position_accuracy * 10.f),
664  cfg_valset_msg_size);
665 
666  if (!sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
667  return -1;
668  }
669 
671  return -1;
672  }
673 
674  // directly enable RTCM3 output
675  return activateRTCMOutput();
676 
677  }
678 
679  return 0;
680 }
681 
682 int // -1 = NAK, error or timeout, 0 = ACK
683 GPSDriverUBX::waitForAck(const uint16_t msg, const unsigned timeout, const bool report)
684 {
685  int ret = -1;
686 
688  _ack_waiting_msg = msg; // memorize sent msg class&ID for ACK check
689 
690  gps_abstime time_started = gps_absolute_time();
691 
692  while ((_ack_state == UBX_ACK_WAITING) && (gps_absolute_time() < time_started + timeout * 1000)) {
693  receive(timeout);
694  }
695 
696  if (_ack_state == UBX_ACK_GOT_ACK) {
697  ret = 0; // ACK received ok
698 
699  } else if (report) {
700  if (_ack_state == UBX_ACK_GOT_NAK) {
701  UBX_DEBUG("ubx msg 0x%04x NAK", SWAP16((unsigned)msg));
702 
703  } else {
704  UBX_DEBUG("ubx msg 0x%04x ACK timeout", SWAP16((unsigned)msg));
705  }
706  }
707 
709  return ret;
710 }
711 
712 int // -1 = error, 0 = no message handled, 1 = message handled, 2 = sat info message handled
713 GPSDriverUBX::receive(unsigned timeout)
714 {
715  uint8_t buf[GPS_READ_BUFFER_SIZE];
716 
717  /* timeout additional to poll */
718  gps_abstime time_started = gps_absolute_time();
719 
720  int handled = 0;
721 
722  while (true) {
723  bool ready_to_return = _configured ? (_got_posllh && _got_velned) : handled;
724 
725  /* Wait for only UBX_PACKET_TIMEOUT if something already received. */
726  int ret = read(buf, sizeof(buf), ready_to_return ? UBX_PACKET_TIMEOUT : timeout);
727 
728  if (ret < 0) {
729  /* something went wrong when polling or reading */
730  UBX_WARN("ubx poll_or_read err");
731  return -1;
732 
733  } else if (ret == 0) {
734  /* return success if ready */
735  if (ready_to_return) {
736  _got_posllh = false;
737  _got_velned = false;
738  return handled;
739  }
740 
741  } else {
742  //UBX_DEBUG("read %d bytes", ret);
743 
744  /* pass received bytes to the packet decoder */
745  for (int i = 0; i < ret; i++) {
746  handled |= parseChar(buf[i]);
747  //UBX_DEBUG("parsed %d: 0x%x", i, buf[i]);
748  }
749 
750  if (_interface == Interface::SPI) {
751  if (buf[ret - 1] == 0xff) {
752  if (ready_to_return) {
753  _got_posllh = false;
754  _got_velned = false;
755  return handled;
756  }
757  }
758  }
759  }
760 
761  /* abort after timeout if no useful packets received */
762  if (time_started + timeout * 1000 < gps_absolute_time()) {
763  UBX_DEBUG("timed out, returning");
764  return -1;
765  }
766  }
767 }
768 
769 int // 0 = decoding, 1 = message handled, 2 = sat info message handled
770 GPSDriverUBX::parseChar(const uint8_t b)
771 {
772  int ret = 0;
773 
774  switch (_decode_state) {
775 
776  /* Expecting Sync1 */
777  case UBX_DECODE_SYNC1:
778  if (b == UBX_SYNC1) { // Sync1 found --> expecting Sync2
779  UBX_TRACE_PARSER("A");
781 
782  } else if (b == RTCM3_PREAMBLE && _rtcm_parsing) {
783  UBX_TRACE_PARSER("RTCM");
786  }
787 
788  break;
789 
790  /* Expecting Sync2 */
791  case UBX_DECODE_SYNC2:
792  if (b == UBX_SYNC2) { // Sync2 found --> expecting Class
793  UBX_TRACE_PARSER("B");
795 
796  } else { // Sync1 not followed by Sync2: reset parser
797  decodeInit();
798  }
799 
800  break;
801 
802  /* Expecting Class */
803  case UBX_DECODE_CLASS:
804  UBX_TRACE_PARSER("C");
805  addByteToChecksum(b); // checksum is calculated for everything except Sync and Checksum bytes
806  _rx_msg = b;
808  break;
809 
810  /* Expecting ID */
811  case UBX_DECODE_ID:
812  UBX_TRACE_PARSER("D");
814  _rx_msg |= b << 8;
816  break;
817 
818  /* Expecting first length byte */
819  case UBX_DECODE_LENGTH1:
820  UBX_TRACE_PARSER("E");
822  _rx_payload_length = b;
824  break;
825 
826  /* Expecting second length byte */
827  case UBX_DECODE_LENGTH2:
828  UBX_TRACE_PARSER("F");
830  _rx_payload_length |= b << 8; // calculate payload size
831 
832  if (payloadRxInit() != 0) { // start payload reception
833  // payload will not be handled, discard message
834  decodeInit();
835 
836  } else {
838  }
839 
840  break;
841 
842  /* Expecting payload */
843  case UBX_DECODE_PAYLOAD:
844  UBX_TRACE_PARSER(".");
846 
847  switch (_rx_msg) {
848  case UBX_MSG_NAV_SAT:
849  ret = payloadRxAddNavSat(b); // add a NAV-SAT payload byte
850  break;
851 
852  case UBX_MSG_NAV_SVINFO:
853  ret = payloadRxAddNavSvinfo(b); // add a NAV-SVINFO payload byte
854  break;
855 
856  case UBX_MSG_MON_VER:
857  ret = payloadRxAddMonVer(b); // add a MON-VER payload byte
858  break;
859 
860  default:
861  ret = payloadRxAdd(b); // add a payload byte
862  break;
863  }
864 
865  if (ret < 0) {
866  // payload not handled, discard message
867  decodeInit();
868 
869  } else if (ret > 0) {
870  // payload complete, expecting checksum
872 
873  } else {
874  // expecting more payload, stay in state UBX_DECODE_PAYLOAD
875  }
876 
877  ret = 0;
878  break;
879 
880  /* Expecting first checksum byte */
881  case UBX_DECODE_CHKSUM1:
882  if (_rx_ck_a != b) {
883  UBX_DEBUG("ubx checksum err");
884  decodeInit();
885 
886  } else {
888  }
889 
890  break;
891 
892  /* Expecting second checksum byte */
893  case UBX_DECODE_CHKSUM2:
894  if (_rx_ck_b != b) {
895  UBX_DEBUG("ubx checksum err");
896 
897  } else {
898  ret = payloadRxDone(); // finish payload processing
899  }
900 
901  decodeInit();
902  break;
903 
904  case UBX_DECODE_RTCM3:
905  if (_rtcm_parsing->addByte(b)) {
906  UBX_DEBUG("got RTCM message with length %i", (int)_rtcm_parsing->messageLength());
908  decodeInit();
909  }
910 
911  break;
912 
913  default:
914  break;
915  }
916 
917  return ret;
918 }
919 
920 /**
921  * Start payload rx
922  */
923 int // -1 = abort, 0 = continue
925 {
926  int ret = 0;
927 
928  _rx_state = UBX_RXMSG_HANDLE; // handle by default
929 
930  switch (_rx_msg) {
931  case UBX_MSG_NAV_PVT:
932  if ((_rx_payload_length != UBX_PAYLOAD_RX_NAV_PVT_SIZE_UBX7) /* u-blox 7 msg format */
933  && (_rx_payload_length != UBX_PAYLOAD_RX_NAV_PVT_SIZE_UBX8)) { /* u-blox 8+ msg format */
935 
936  } else if (!_configured) {
937  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
938 
939  } else if (!_use_nav_pvt) {
940  _rx_state = UBX_RXMSG_DISABLE; // disable if not using NAV-PVT
941  }
942 
943  break;
944 
945  case UBX_MSG_INF_DEBUG:
946  case UBX_MSG_INF_ERROR:
947  case UBX_MSG_INF_NOTICE:
948  case UBX_MSG_INF_WARNING:
949  if (_rx_payload_length >= sizeof(ubx_buf_t)) {
950  _rx_payload_length = sizeof(ubx_buf_t) - 1; //avoid buffer overflow
951  }
952 
953  break;
954 
955  case UBX_MSG_NAV_POSLLH:
958 
959  } else if (!_configured) {
960  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
961 
962  } else if (_use_nav_pvt) {
963  _rx_state = UBX_RXMSG_DISABLE; // disable if using NAV-PVT instead
964  }
965 
966  break;
967 
968  case UBX_MSG_NAV_SOL:
971 
972  } else if (!_configured) {
973  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
974 
975  } else if (_use_nav_pvt) {
976  _rx_state = UBX_RXMSG_DISABLE; // disable if using NAV-PVT instead
977  }
978 
979  break;
980 
981  case UBX_MSG_NAV_DOP:
984 
985  } else if (!_configured) {
986  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
987 
988  }
989 
990  break;
991 
992  case UBX_MSG_NAV_TIMEUTC:
995 
996  } else if (!_configured) {
997  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
998 
999  } else if (_use_nav_pvt) {
1000  _rx_state = UBX_RXMSG_DISABLE; // disable if using NAV-PVT instead
1001  }
1002 
1003  break;
1004 
1005  case UBX_MSG_NAV_SAT:
1006  case UBX_MSG_NAV_SVINFO:
1007  if (_satellite_info == nullptr) {
1008  _rx_state = UBX_RXMSG_DISABLE; // disable if sat info not requested
1009 
1010  } else if (!_configured) {
1011  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
1012 
1013  } else {
1014  memset(_satellite_info, 0, sizeof(*_satellite_info)); // initialize sat info
1015  }
1016 
1017  break;
1018 
1019  case UBX_MSG_NAV_SVIN:
1022 
1023  } else if (!_configured) {
1024  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
1025 
1026  }
1027 
1028  break;
1029 
1030  case UBX_MSG_NAV_VELNED:
1033 
1034  } else if (!_configured) {
1035  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
1036 
1037  } else if (_use_nav_pvt) {
1038  _rx_state = UBX_RXMSG_DISABLE; // disable if using NAV-PVT instead
1039  }
1040 
1041  break;
1042 
1043  case UBX_MSG_MON_VER:
1044  break; // unconditionally handle this message
1045 
1046  case UBX_MSG_MON_HW:
1047  if ((_rx_payload_length != sizeof(ubx_payload_rx_mon_hw_ubx6_t)) /* u-blox 6 msg format */
1048  && (_rx_payload_length != sizeof(ubx_payload_rx_mon_hw_ubx7_t))) { /* u-blox 7+ msg format */
1050 
1051  } else if (!_configured) {
1052  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
1053  }
1054 
1055  break;
1056 
1057  case UBX_MSG_MON_RF:
1060 
1062 
1063  } else if (!_configured) {
1064  _rx_state = UBX_RXMSG_IGNORE; // ignore if not _configured
1065  }
1066 
1067  break;
1068 
1069  case UBX_MSG_ACK_ACK:
1072 
1073  } else if (_configured) {
1074  _rx_state = UBX_RXMSG_IGNORE; // ignore if _configured
1075  }
1076 
1077  break;
1078 
1079  case UBX_MSG_ACK_NAK:
1082 
1083  } else if (_configured) {
1084  _rx_state = UBX_RXMSG_IGNORE; // ignore if _configured
1085  }
1086 
1087  break;
1088 
1089  default:
1090  _rx_state = UBX_RXMSG_DISABLE; // disable all other messages
1091  break;
1092  }
1093 
1094  switch (_rx_state) {
1095  case UBX_RXMSG_HANDLE: // handle message
1096  case UBX_RXMSG_IGNORE: // ignore message but don't report error
1097  ret = 0;
1098  break;
1099 
1100  case UBX_RXMSG_DISABLE: // disable unexpected messages
1101  UBX_DEBUG("ubx msg 0x%04x len %u unexpected", SWAP16((unsigned)_rx_msg), (unsigned)_rx_payload_length);
1102 
1103  if (!_proto_ver_27_or_higher) { // we cannot infer the config Key ID from _rx_msg for protocol version 27+
1105 
1107  /* don't attempt for every message to disable, some might not be disabled */
1108  _disable_cmd_last = t;
1109  UBX_DEBUG("ubx disabling msg 0x%04x", SWAP16((unsigned)_rx_msg));
1110 
1111  if (!configureMessageRate(_rx_msg, 0)) {
1112  ret = -1;
1113  }
1114  }
1115  }
1116 
1117  ret = -1; // return error, abort handling this message
1118  break;
1119 
1120  case UBX_RXMSG_ERROR_LENGTH: // error: invalid length
1121  UBX_WARN("ubx msg 0x%04x invalid len %u", SWAP16((unsigned)_rx_msg), (unsigned)_rx_payload_length);
1122  ret = -1; // return error, abort handling this message
1123  break;
1124 
1125  default: // invalid message state
1126  UBX_WARN("ubx internal err1");
1127  ret = -1; // return error, abort handling this message
1128  break;
1129  }
1130 
1131  return ret;
1132 }
1133 
1134 /**
1135  * Add payload rx byte
1136  */
1137 int // -1 = error, 0 = ok, 1 = payload completed
1139 {
1140  int ret = 0;
1141  uint8_t *p_buf = (uint8_t *)&_buf;
1142 
1143  p_buf[_rx_payload_index] = b;
1144 
1146  ret = 1; // payload received completely
1147  }
1148 
1149  return ret;
1150 }
1151 
1152 int // -1 = error, 0 = ok, 1 = payload completed
1154 {
1155  int ret = 0;
1156  uint8_t *p_buf = (uint8_t *)&_buf;
1157 
1159  // Fill Part 1 buffer
1160  p_buf[_rx_payload_index] = b;
1161 
1162  } else {
1164  // Part 1 complete: decode Part 1 buffer
1165  _satellite_info->count = MIN(_buf.payload_rx_nav_sat_part1.numSvs, satellite_info_s::SAT_INFO_MAX_SATELLITES);
1166  UBX_TRACE_SVINFO("SAT len %u numCh %u", (unsigned)_rx_payload_length,
1168  }
1169 
1172  // Still room in _satellite_info: fill Part 2 buffer
1173  unsigned buf_index = (_rx_payload_index - sizeof(ubx_payload_rx_nav_sat_part1_t)) % sizeof(
1175  p_buf[buf_index] = b;
1176 
1177  if (buf_index == sizeof(ubx_payload_rx_nav_sat_part2_t) - 1) {
1178  // Part 2 complete: decode Part 2 buffer
1179  unsigned sat_index = (_rx_payload_index - sizeof(ubx_payload_rx_nav_sat_part1_t)) / sizeof(
1181  _satellite_info->used[sat_index] = (uint8_t)(_buf.payload_rx_nav_sat_part2.flags & 0x01);
1182  _satellite_info->snr[sat_index] = (uint8_t)(_buf.payload_rx_nav_sat_part2.cno);
1183  _satellite_info->elevation[sat_index] = (uint8_t)(_buf.payload_rx_nav_sat_part2.elev);
1184  _satellite_info->azimuth[sat_index] = (uint8_t)((float)_buf.payload_rx_nav_sat_part2.azim * 255.0f / 360.0f);
1185  _satellite_info->svid[sat_index] = (uint8_t)(_buf.payload_rx_nav_sat_part2.svId);
1186  UBX_TRACE_SVINFO("SAT #%02u used %u snr %3u elevation %3u azimuth %3u svid %3u",
1187  (unsigned)sat_index + 1,
1188  (unsigned)_satellite_info->used[sat_index],
1189  (unsigned)_satellite_info->snr[sat_index],
1190  (unsigned)_satellite_info->elevation[sat_index],
1191  (unsigned)_satellite_info->azimuth[sat_index],
1192  (unsigned)_satellite_info->svid[sat_index]
1193  );
1194  }
1195  }
1196  }
1197 
1199  ret = 1; // payload received completely
1200  }
1201 
1202  return ret;
1203 }
1204 /**
1205  * Add NAV-SVINFO payload rx byte
1206  */
1207 int // -1 = error, 0 = ok, 1 = payload completed
1209 {
1210  int ret = 0;
1211  uint8_t *p_buf = (uint8_t *)&_buf;
1212 
1214  // Fill Part 1 buffer
1215  p_buf[_rx_payload_index] = b;
1216 
1217  } else {
1219  // Part 1 complete: decode Part 1 buffer
1220  _satellite_info->count = MIN(_buf.payload_rx_nav_svinfo_part1.numCh, satellite_info_s::SAT_INFO_MAX_SATELLITES);
1221  UBX_TRACE_SVINFO("SVINFO len %u numCh %u", (unsigned)_rx_payload_length,
1223  }
1224 
1227  // Still room in _satellite_info: fill Part 2 buffer
1228  unsigned buf_index = (_rx_payload_index - sizeof(ubx_payload_rx_nav_svinfo_part1_t)) % sizeof(
1230  p_buf[buf_index] = b;
1231 
1232  if (buf_index == sizeof(ubx_payload_rx_nav_svinfo_part2_t) - 1) {
1233  // Part 2 complete: decode Part 2 buffer
1234  unsigned sat_index = (_rx_payload_index - sizeof(ubx_payload_rx_nav_svinfo_part1_t)) / sizeof(
1236  _satellite_info->used[sat_index] = (uint8_t)(_buf.payload_rx_nav_svinfo_part2.flags & 0x01);
1237  _satellite_info->snr[sat_index] = (uint8_t)(_buf.payload_rx_nav_svinfo_part2.cno);
1239  _satellite_info->azimuth[sat_index] = (uint8_t)((float)_buf.payload_rx_nav_svinfo_part2.azim * 255.0f / 360.0f);
1240  _satellite_info->svid[sat_index] = (uint8_t)(_buf.payload_rx_nav_svinfo_part2.svid);
1241  UBX_TRACE_SVINFO("SVINFO #%02u used %u snr %3u elevation %3u azimuth %3u svid %3u",
1242  (unsigned)sat_index + 1,
1243  (unsigned)_satellite_info->used[sat_index],
1244  (unsigned)_satellite_info->snr[sat_index],
1245  (unsigned)_satellite_info->elevation[sat_index],
1246  (unsigned)_satellite_info->azimuth[sat_index],
1247  (unsigned)_satellite_info->svid[sat_index]
1248  );
1249  }
1250  }
1251  }
1252 
1254  ret = 1; // payload received completely
1255  }
1256 
1257  return ret;
1258 }
1259 
1260 /**
1261  * Add MON-VER payload rx byte
1262  */
1263 int // -1 = error, 0 = ok, 1 = payload completed
1265 {
1266  int ret = 0;
1267  uint8_t *p_buf = (uint8_t *)&_buf;
1268 
1270  // Fill Part 1 buffer
1271  p_buf[_rx_payload_index] = b;
1272 
1273  } else {
1275  // Part 1 complete: decode Part 1 buffer and calculate hash for SW&HW version strings
1278  UBX_DEBUG("VER hash 0x%08x", _ubx_version);
1279  UBX_DEBUG("VER hw \"%10s\"", _buf.payload_rx_mon_ver_part1.hwVersion);
1280  UBX_DEBUG("VER sw \"%30s\"", _buf.payload_rx_mon_ver_part1.swVersion);
1281 
1282  // Device detection (See https://forum.u-blox.com/index.php/9432/need-help-decoding-ubx-mon-ver-hardware-string)
1283  if (strncmp((const char *)_buf.payload_rx_mon_ver_part1.hwVersion, "00040005",
1284  sizeof(_buf.payload_rx_mon_ver_part1.hwVersion)) == 0) {
1286 
1287  } else if (strncmp((const char *)_buf.payload_rx_mon_ver_part1.hwVersion, "00040007",
1288  sizeof(_buf.payload_rx_mon_ver_part1.hwVersion)) == 0) {
1290 
1291  } else if (strncmp((const char *)_buf.payload_rx_mon_ver_part1.hwVersion, "00070000",
1292  sizeof(_buf.payload_rx_mon_ver_part1.hwVersion)) == 0) {
1294 
1295  } else if (strncmp((const char *)_buf.payload_rx_mon_ver_part1.hwVersion, "00080000",
1296  sizeof(_buf.payload_rx_mon_ver_part1.hwVersion)) == 0) {
1298 
1299  } else if (strncmp((const char *)_buf.payload_rx_mon_ver_part1.hwVersion, "00190000",
1300  sizeof(_buf.payload_rx_mon_ver_part1.hwVersion)) == 0) {
1302 
1303  } else {
1304  UBX_WARN("unknown board hw: %s", _buf.payload_rx_mon_ver_part1.hwVersion);
1305  }
1306 
1307  UBX_DEBUG("detected board: %i", (int)_board);
1308  }
1309 
1310  // fill Part 2 buffer
1311  unsigned buf_index = (_rx_payload_index - sizeof(ubx_payload_rx_mon_ver_part1_t)) % sizeof(
1313  p_buf[buf_index] = b;
1314 
1315  if (buf_index == sizeof(ubx_payload_rx_mon_ver_part2_t) - 1) {
1316  // Part 2 complete: decode Part 2 buffer
1317  UBX_DEBUG("VER ext \" %30s\"", _buf.payload_rx_mon_ver_part2.extension);
1318  }
1319  }
1320 
1322  ret = 1; // payload received completely
1323  }
1324 
1325  return ret;
1326 }
1327 
1328 /**
1329  * Finish payload rx
1330  */
1331 int // 0 = no message handled, 1 = message handled, 2 = sat info message handled
1333 {
1334  int ret = 0;
1335 
1336  // return if no message handled
1337  if (_rx_state != UBX_RXMSG_HANDLE) {
1338  return ret;
1339  }
1340 
1341  // handle message
1342  switch (_rx_msg) {
1343 
1344  case UBX_MSG_NAV_PVT:
1345  UBX_TRACE_RXMSG("Rx NAV-PVT");
1346 
1347  //Check if position fix flag is good
1350 
1352  _gps_position->fix_type = 4; //DGPS
1353  }
1354 
1355  uint8_t carr_soln = _buf.payload_rx_nav_pvt.flags >> 6;
1356 
1357  if (carr_soln == 1) {
1358  _gps_position->fix_type = 5; //Float RTK
1359 
1360  } else if (carr_soln == 2) {
1361  _gps_position->fix_type = 6; //Fixed RTK
1362  }
1363 
1364  _gps_position->vel_ned_valid = true;
1365 
1366  } else {
1367  _gps_position->fix_type = 0;
1368  _gps_position->vel_ned_valid = false;
1369  }
1370 
1372 
1377 
1378  _gps_position->eph = (float)_buf.payload_rx_nav_pvt.hAcc * 1e-3f;
1379  _gps_position->epv = (float)_buf.payload_rx_nav_pvt.vAcc * 1e-3f;
1381 
1383 
1387 
1388  _gps_position->cog_rad = (float)_buf.payload_rx_nav_pvt.headMot * M_DEG_TO_RAD_F * 1e-5f;
1389  _gps_position->c_variance_rad = (float)_buf.payload_rx_nav_pvt.headAcc * M_DEG_TO_RAD_F * 1e-5f;
1390 
1391  //Check if time and date fix flags are good
1395  /* convert to unix timestamp */
1396  tm timeinfo{};
1397  timeinfo.tm_year = _buf.payload_rx_nav_pvt.year - 1900;
1398  timeinfo.tm_mon = _buf.payload_rx_nav_pvt.month - 1;
1399  timeinfo.tm_mday = _buf.payload_rx_nav_pvt.day;
1400  timeinfo.tm_hour = _buf.payload_rx_nav_pvt.hour;
1401  timeinfo.tm_min = _buf.payload_rx_nav_pvt.min;
1402  timeinfo.tm_sec = _buf.payload_rx_nav_pvt.sec;
1403 
1404 #ifndef NO_MKTIME
1405  time_t epoch = mktime(&timeinfo);
1406 
1407  if (epoch > GPS_EPOCH_SECS) {
1408  // FMUv2+ boards have a hardware RTC, but GPS helps us to configure it
1409  // and control its drift. Since we rely on the HRT for our monotonic
1410  // clock, updating it from time to time is safe.
1411 
1412  timespec ts{};
1413  ts.tv_sec = epoch;
1414  ts.tv_nsec = _buf.payload_rx_nav_pvt.nano;
1415 
1416  setClock(ts);
1417 
1418  _gps_position->time_utc_usec = static_cast<uint64_t>(epoch) * 1000000ULL;
1420 
1421  } else {
1423  }
1424 
1425 #else
1427 #endif
1428  }
1429 
1432 
1433  _rate_count_vel++;
1435 
1436  _got_posllh = true;
1437  _got_velned = true;
1438 
1439  ret = 1;
1440  break;
1441 
1442  case UBX_MSG_INF_DEBUG:
1443  case UBX_MSG_INF_NOTICE: {
1444  uint8_t *p_buf = (uint8_t *)&_buf;
1445  p_buf[_rx_payload_length] = 0;
1446  UBX_DEBUG("ubx msg: %s", p_buf);
1447  }
1448  break;
1449 
1450  case UBX_MSG_INF_ERROR:
1451  case UBX_MSG_INF_WARNING: {
1452  uint8_t *p_buf = (uint8_t *)&_buf;
1453  p_buf[_rx_payload_length] = 0;
1454  UBX_WARN("ubx msg: %s", p_buf);
1455  }
1456  break;
1457 
1458  case UBX_MSG_NAV_POSLLH:
1459  UBX_TRACE_RXMSG("Rx NAV-POSLLH");
1460 
1464  _gps_position->eph = (float)_buf.payload_rx_nav_posllh.hAcc * 1e-3f; // from mm to m
1465  _gps_position->epv = (float)_buf.payload_rx_nav_posllh.vAcc * 1e-3f; // from mm to m
1467 
1469 
1471  _got_posllh = true;
1472 
1473  ret = 1;
1474  break;
1475 
1476  case UBX_MSG_NAV_SOL:
1477  UBX_TRACE_RXMSG("Rx NAV-SOL");
1478 
1480  _gps_position->s_variance_m_s = (float)_buf.payload_rx_nav_sol.sAcc * 1e-2f; // from cm to m
1482 
1483  ret = 1;
1484  break;
1485 
1486  case UBX_MSG_NAV_DOP:
1487  UBX_TRACE_RXMSG("Rx NAV-DOP");
1488 
1489  _gps_position->hdop = _buf.payload_rx_nav_dop.hDOP * 0.01f; // from cm to m
1490  _gps_position->vdop = _buf.payload_rx_nav_dop.vDOP * 0.01f; // from cm to m
1491 
1492  ret = 1;
1493  break;
1494 
1495  case UBX_MSG_NAV_TIMEUTC:
1496  UBX_TRACE_RXMSG("Rx NAV-TIMEUTC");
1497 
1499  // convert to unix timestamp
1500  tm timeinfo {};
1501  timeinfo.tm_year = _buf.payload_rx_nav_timeutc.year - 1900;
1502  timeinfo.tm_mon = _buf.payload_rx_nav_timeutc.month - 1;
1503  timeinfo.tm_mday = _buf.payload_rx_nav_timeutc.day;
1504  timeinfo.tm_hour = _buf.payload_rx_nav_timeutc.hour;
1505  timeinfo.tm_min = _buf.payload_rx_nav_timeutc.min;
1506  timeinfo.tm_sec = _buf.payload_rx_nav_timeutc.sec;
1507  timeinfo.tm_isdst = 0;
1508 #ifndef NO_MKTIME
1509  time_t epoch = mktime(&timeinfo);
1510 
1511  // only set the time if it makes sense
1512 
1513  if (epoch > GPS_EPOCH_SECS) {
1514  // FMUv2+ boards have a hardware RTC, but GPS helps us to configure it
1515  // and control its drift. Since we rely on the HRT for our monotonic
1516  // clock, updating it from time to time is safe.
1517 
1518  timespec ts{};
1519  ts.tv_sec = epoch;
1520  ts.tv_nsec = _buf.payload_rx_nav_timeutc.nano;
1521 
1522  setClock(ts);
1523 
1524  _gps_position->time_utc_usec = static_cast<uint64_t>(epoch) * 1000000ULL;
1526 
1527  } else {
1529  }
1530 
1531 #else
1533 #endif
1534  }
1535 
1537 
1538  ret = 1;
1539  break;
1540 
1541  case UBX_MSG_NAV_SAT:
1542  case UBX_MSG_NAV_SVINFO:
1543  UBX_TRACE_RXMSG("Rx NAV-SVINFO");
1544 
1545  // _satellite_info already populated by payload_rx_add_svinfo(), just add a timestamp
1547 
1548  ret = 2;
1549  break;
1550 
1551  case UBX_MSG_NAV_SVIN:
1552  UBX_TRACE_RXMSG("Rx NAV-SVIN");
1553  {
1555 
1556  UBX_DEBUG("Survey-in status: %is cur accuracy: %imm nr obs: %i valid: %i active: %i",
1557  svin.dur, svin.meanAcc / 10, svin.obs, (int)svin.valid, (int)svin.active);
1558 
1560  double ecef_x = ((double)svin.meanX + (double)svin.meanXHP * 0.01) * 0.01;
1561  double ecef_y = ((double)svin.meanY + (double)svin.meanYHP * 0.01) * 0.01;
1562  double ecef_z = ((double)svin.meanZ + (double)svin.meanZHP * 0.01) * 0.01;
1563  ECEF2lla(ecef_x, ecef_y, ecef_z, status.latitude, status.longitude, status.altitude);
1564  status.duration = svin.dur;
1565  status.mean_accuracy = svin.meanAcc / 10;
1566  status.flags = (svin.valid & 1) | ((svin.active & 1) << 1);
1568 
1569  if (svin.valid == 1 && svin.active == 0) {
1570  if (activateRTCMOutput() != 0) {
1571  return -1;
1572  }
1573  }
1574  }
1575 
1576  ret = 1;
1577  break;
1578 
1579  case UBX_MSG_NAV_VELNED:
1580  UBX_TRACE_RXMSG("Rx NAV-VELNED");
1581 
1583  _gps_position->vel_n_m_s = (float)_buf.payload_rx_nav_velned.velN * 1e-2f; /* NED NORTH velocity */
1584  _gps_position->vel_e_m_s = (float)_buf.payload_rx_nav_velned.velE * 1e-2f; /* NED EAST velocity */
1585  _gps_position->vel_d_m_s = (float)_buf.payload_rx_nav_velned.velD * 1e-2f; /* NED DOWN velocity */
1586  _gps_position->cog_rad = (float)_buf.payload_rx_nav_velned.heading * M_DEG_TO_RAD_F * 1e-5f;
1587  _gps_position->c_variance_rad = (float)_buf.payload_rx_nav_velned.cAcc * M_DEG_TO_RAD_F * 1e-5f;
1588  _gps_position->vel_ned_valid = true;
1589 
1590  _rate_count_vel++;
1591  _got_velned = true;
1592 
1593  ret = 1;
1594  break;
1595 
1596  case UBX_MSG_MON_VER:
1597  UBX_TRACE_RXMSG("Rx MON-VER");
1598 
1599  // This is polled only on startup, and the startup code waits for an ack
1602  }
1603 
1604  ret = 1;
1605  break;
1606 
1607  case UBX_MSG_MON_HW:
1608  UBX_TRACE_RXMSG("Rx MON-HW");
1609 
1610  switch (_rx_payload_length) {
1611 
1612  case sizeof(ubx_payload_rx_mon_hw_ubx6_t): /* u-blox 6 msg format */
1615 
1616  ret = 1;
1617  break;
1618 
1619  case sizeof(ubx_payload_rx_mon_hw_ubx7_t): /* u-blox 7+ msg format */
1622 
1623  ret = 1;
1624  break;
1625 
1626  default: // unexpected payload size:
1627  ret = 0; // don't handle message
1628  break;
1629  }
1630 
1631  break;
1632 
1633  case UBX_MSG_MON_RF:
1634  UBX_TRACE_RXMSG("Rx MON-RF");
1635 
1638 
1639  ret = 1;
1640  break;
1641 
1642  case UBX_MSG_ACK_ACK:
1643  UBX_TRACE_RXMSG("Rx ACK-ACK");
1644 
1647  }
1648 
1649  ret = 1;
1650  break;
1651 
1652  case UBX_MSG_ACK_NAK:
1653  UBX_TRACE_RXMSG("Rx ACK-NAK");
1654 
1657  }
1658 
1659  ret = 1;
1660  break;
1661 
1662  default:
1663  break;
1664  }
1665 
1666  if (ret > 0) {
1668  }
1669 
1670  return ret;
1671 }
1672 
1673 int
1675 {
1676  /* We now switch to 1 Hz update rate, which is enough for RTCM output.
1677  * For the survey-in, we still want 5/10 Hz, because this speeds up the process */
1678 
1680  int cfg_valset_msg_size = initCfgValset();
1681 
1682  cfgValset<uint16_t>(UBX_CFG_KEY_RATE_MEAS, 1000, cfg_valset_msg_size);
1683  cfgValsetPort(UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1005_I2C, 5, cfg_valset_msg_size);
1684  cfgValsetPort(UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1077_I2C, 1, cfg_valset_msg_size);
1685  cfgValsetPort(UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1087_I2C, 1, cfg_valset_msg_size);
1686  cfgValsetPort(UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1230_I2C, 1, cfg_valset_msg_size);
1687  cfgValsetPort(UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1097_I2C, 1, cfg_valset_msg_size);
1688  cfgValsetPort(UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1127_I2C, 1, cfg_valset_msg_size);
1689  cfgValsetPort(UBX_CFG_KEY_MSGOUT_UBX_NAV_SVIN_I2C, 0, cfg_valset_msg_size);
1690 
1691  if (!sendMessage(UBX_MSG_CFG_VALSET, (uint8_t *)&_buf, cfg_valset_msg_size)) {
1692  return -1;
1693  }
1694 
1696  return -1;
1697  }
1698 
1699  } else {
1700 
1701  memset(&_buf.payload_tx_cfg_rate, 0, sizeof(_buf.payload_tx_cfg_rate));
1705 
1706  if (!sendMessage(UBX_MSG_CFG_RATE, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_rate))) { return -1; }
1707 
1708  // according to the spec we should receive an (N)ACK here, but we don't
1709 // decodeInit();
1710 // if (waitForAck(UBX_MSG_CFG_RATE, UBX_CONFIG_TIMEOUT, true) < 0) {
1711 // return -1;
1712 // }
1713 
1715 
1716  // stationary RTK reference station ARP (can be sent at lower rate)
1717  if (!configureMessageRate(UBX_MSG_RTCM3_1005, 5)) { return -1; }
1718 
1719  // GPS
1720  if (!configureMessageRate(UBX_MSG_RTCM3_1077, 1)) { return -1; }
1721 
1722  // GLONASS
1723  if (!configureMessageRate(UBX_MSG_RTCM3_1087, 1)) { return -1; }
1724 
1725  // GLONASS code-phase biases
1726  if (!configureMessageRate(UBX_MSG_RTCM3_1230, 1)) { return -1; }
1727 
1728  // Galileo
1729  if (!configureMessageRate(UBX_MSG_RTCM3_1097, 1)) { return -1; }
1730 
1731  // BeiDou
1732  if (!configureMessageRate(UBX_MSG_RTCM3_1127, 1)) { return -1; }
1733  }
1734 
1735  return 0;
1736 }
1737 
1738 void
1740 {
1742  _rx_ck_a = 0;
1743  _rx_ck_b = 0;
1744  _rx_payload_length = 0;
1745  _rx_payload_index = 0;
1746 
1747  if (_output_mode == OutputMode::RTCM) {
1748  if (!_rtcm_parsing) {
1749  _rtcm_parsing = new RTCMParsing();
1750  }
1751 
1752  _rtcm_parsing->reset();
1753  }
1754 }
1755 
1756 void
1758 {
1759  _rx_ck_a = _rx_ck_a + b;
1761 }
1762 
1763 void
1764 GPSDriverUBX::calcChecksum(const uint8_t *buffer, const uint16_t length, ubx_checksum_t *checksum)
1765 {
1766  for (uint16_t i = 0; i < length; i++) {
1767  checksum->ck_a = checksum->ck_a + buffer[i];
1768  checksum->ck_b = checksum->ck_b + checksum->ck_a;
1769  }
1770 }
1771 
1772 bool
1773 GPSDriverUBX::configureMessageRate(const uint16_t msg, const uint8_t rate)
1774 {
1776  // configureMessageRate() should not be called if _proto_ver_27_or_higher is true.
1777  // If you see this message the calling code needs to be fixed.
1778  UBX_WARN("FIXME: use of deprecated msg CFG_MSG (%i %i)", msg, rate);
1779  }
1780 
1781  ubx_payload_tx_cfg_msg_t cfg_msg; // don't use _buf (allow interleaved operation)
1782  memset(&cfg_msg, 0, sizeof(cfg_msg));
1783 
1784  cfg_msg.msg = msg;
1785  cfg_msg.rate = rate;
1786 
1787  return sendMessage(UBX_MSG_CFG_MSG, (uint8_t *)&cfg_msg, sizeof(cfg_msg));
1788 }
1789 
1790 bool
1791 GPSDriverUBX::configureMessageRateAndAck(uint16_t msg, uint8_t rate, bool report_ack_error)
1792 {
1793  if (!configureMessageRate(msg, rate)) {
1794  return false;
1795  }
1796 
1797  return waitForAck(UBX_MSG_CFG_MSG, UBX_CONFIG_TIMEOUT, report_ack_error) >= 0;
1798 }
1799 
1800 bool
1801 GPSDriverUBX::sendMessage(const uint16_t msg, const uint8_t *payload, const uint16_t length)
1802 {
1803  ubx_header_t header = {UBX_SYNC1, UBX_SYNC2, 0, 0};
1804  ubx_checksum_t checksum = {0, 0};
1805 
1806  // Populate header
1807  header.msg = msg;
1808  header.length = length;
1809 
1810  // Calculate checksum
1811  calcChecksum(((uint8_t *)&header) + 2, sizeof(header) - 2, &checksum); // skip 2 sync bytes
1812 
1813  if (payload != nullptr) {
1814  calcChecksum(payload, length, &checksum);
1815  }
1816 
1817  // Send message
1818  if (write((void *)&header, sizeof(header)) != sizeof(header)) {
1819  return false;
1820  }
1821 
1822  if (payload && write((void *)payload, length) != length) {
1823  return false;
1824  }
1825 
1826  if (write((void *)&checksum, sizeof(checksum)) != sizeof(checksum)) {
1827  return false;
1828  }
1829 
1830  return true;
1831 }
1832 
1833 uint32_t
1834 GPSDriverUBX::fnv1_32_str(uint8_t *str, uint32_t hval)
1835 {
1836  uint8_t *s = str;
1837 
1838  /*
1839  * FNV-1 hash each octet in the buffer
1840  */
1841  while (*s) {
1842 
1843  /* multiply by the 32 bit FNV magic prime mod 2^32 */
1844 #if defined(NO_FNV_GCC_OPTIMIZATION)
1845  hval *= FNV1_32_PRIME;
1846 #else
1847  hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
1848 #endif
1849 
1850  /* xor the bottom with the current octet */
1851  hval ^= (uint32_t) * s++;
1852  }
1853 
1854  /* return our new hash value */
1855  return hval;
1856 }
1857 
1858 int
1860 {
1861  memset(&_buf.payload_tx_cfg_rst, 0, sizeof(_buf.payload_tx_cfg_rst));
1863 
1864  switch (restart_type) {
1865  case GPSRestartType::Hot:
1867  break;
1868 
1869  case GPSRestartType::Warm:
1871  break;
1872 
1873  case GPSRestartType::Cold:
1875  break;
1876 
1877  default:
1878  return -2;
1879  }
1880 
1881  if (sendMessage(UBX_MSG_CFG_RST, (uint8_t *)&_buf, sizeof(_buf.payload_tx_cfg_rst))) {
1882  return 0;
1883  }
1884 
1885  return -2;
1886 }
#define UBX_CFG_KEY_RATE_MEAS
Definition: ubx.h:268
#define UBX_MSG_INF_NOTICE
Definition: ubx.h:128
void surveyInStatus(SurveyInStatus &status)
Definition: gps_helper.h:233
#define UBX_TX_CFG_PRT_INPROTOMASK_RTCM
UBX in.
Definition: ubx.h:188
uint32_t cAcc
Course / Heading accuracy estimate [1e-5 deg].
Definition: ubx.h:485
ubx_payload_tx_cfg_rst_t payload_tx_cfg_rst
Definition: ubx.h:718
#define UBX_TX_CFG_RST_BBR_MODE_WARM_START
Definition: ubx.h:210
int restartSurveyIn()
Start or restart the survey-in procees.
Definition: ubx.cpp:609
#define DISABLE_MSG_INTERVAL
Definition: ubx.cpp:64
const Interface _interface
Definition: ubx.h:932
ubx_payload_rx_nav_svinfo_part2_t payload_rx_nav_svinfo_part2
Definition: ubx.h:703
void addByteToChecksum(const uint8_t)
While parsing add every byte (except the sync bytes) to the checksum.
Definition: ubx.cpp:1757
uint32_t hAcc
Horizontal accuracy estimate [mm].
Definition: ubx.h:327
#define UBX_CFG_KEY_RATE_NAV
Definition: ubx.h:269
#define UBX_TX_CFG_NAV5_FIXMODE
1 2D only, 2 3D only, 3 Auto 2D/3D
Definition: ubx.h:205
uint8_t ck_b
Definition: ubx.h:317
uint8_t min
Minute of hour, range 0..59 (UTC)
Definition: ubx.h:411
#define UBX_CFG_KEY_TMODE_HEIGHT
Definition: ubx.h:276
#define UBX_CFG_KEY_CFG_UART1_PARITY
Definition: ubx.h:219
ubx_payload_rx_mon_hw_ubx6_t payload_rx_mon_hw_ubx6
Definition: ubx.h:708
#define UBX_PAYLOAD_RX_NAV_PVT_SIZE_UBX8
Definition: ubx.h:400
uint16_t timeRef
Alignment to reference time: 0 = UTC time, 1 = GPS time.
Definition: ubx.h:602
#define UBX_CFG_KEY_NAVSPG_UTCSTANDARD
Definition: ubx.h:260
union GPSBaseStationSupport::BaseSettings::@4 settings
static struct vehicle_status_s status
Definition: Commander.cpp:138
#define UBX_CFG_KEY_MSGOUT_UBX_MON_RF_I2C
Definition: ubx.h:284
#define UBX_CFG_KEY_SPI_ENABLED
Definition: ubx.h:296
#define UBX_CFG_LAYER_RAM
Definition: ubx.h:621
uint8_t ck_a
Definition: ubx.h:316
#define UBX_MSG_RTCM3_1127
Definition: ubx.h:154
#define UBX_DEBUG(...)
Definition: ubx.cpp:80
Board _board
Definition: ubx.h:933
uint16_t navBbrMask
Definition: ubx.h:651
int restartSurveyInPreV27()
restartSurveyIn for protocol version < 27 (_proto_ver_27_or_higher == false)
Definition: ubx.cpp:530
GPSRestartType
Definition: gps_helper.h:101
#define UBX_CFG_KEY_CFG_UART1_BAUDRATE
Definition: ubx.h:216
uint8_t numCh
Number of channels.
Definition: ubx.h:419
#define UBX_CFG_KEY_TMODE_POS_TYPE
Definition: ubx.h:273
#define UBX_MSG_INF_ERROR
Definition: ubx.h:127
#define UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1230_I2C
Definition: ubx.h:294
#define UBX_CFG_KEY_TMODE_LAT
Definition: ubx.h:274
int32_t height
Height above ellipsoid [mm].
Definition: ubx.h:325
ubx_payload_rx_nav_posllh_t payload_rx_nav_posllh
Definition: ubx.h:698
#define UBX_PAYLOAD_RX_NAV_PVT_SIZE_UBX7
Definition: ubx.h:399
#define UBX_MSG_MON_HW
Definition: ubx.h:143
uint64_t _last_timestamp_time
Definition: ubx.h:910
uint8_t used[20]
uint32_t hAcc
Horizontal accuracy estimate [mm].
Definition: ubx.h:384
#define UBX_CFG_KEY_TMODE_HEIGHT_HP
Definition: ubx.h:279
int setBaudrate(int baudrate)
set the Baudrate
Definition: gps_helper.h:228
uint8_t azimuth[20]
uint16_t navRate
Navigation Rate, in number of measurement cycles.
Definition: ubx.h:601
#define UBX_TX_CFG_PRT_BAUDRATE
choose 38400 as GPS baudrate (pre M8* boards only)
Definition: ubx.h:186
uint8_t _dyn_model
Definition: ubx.h:936
uint32_t vAcc
Vertical accuracy estimate [mm].
Definition: ubx.h:328
uint8_t gpsFix
GPSfix type: 0 = No fix, 1 = Dead Reckoning only, 2 = 2D fix, 3 = 3d-fix, 4 = GPS + dead reckoning...
Definition: ubx.h:348
uint8_t month
Month, range 1..12 (UTC)
Definition: ubx.h:408
#define UBX_RX_NAV_TIMEUTC_VALID_VALIDUTC
validUTC (1 = Valid UTC Time)
Definition: ubx.h:175
#define UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1005_I2C
Definition: ubx.h:289
#define UBX_CFG_KEY_CFG_SPIINPROT_RTCM3X
Definition: ubx.h:252
ubx_payload_rx_mon_hw_ubx7_t payload_rx_mon_hw_ubx7
Definition: ubx.h:709
#define FNV1_32_PRIME
Definition: ubx.cpp:70
uint8_t valid
Validity Flags (see UBX_RX_NAV_TIMEUTC_VALID_...)
Definition: ubx.h:413
#define UBX_MSG_NAV_SVIN
Definition: ubx.h:124
uint16_t year
Year, range 1999..2099 (UTC)
Definition: ubx.h:407
ubx_payload_rx_nav_timeutc_t payload_rx_nav_timeutc
Definition: ubx.h:701
uint16_t msg
Definition: ubx.h:310
bool cfgValsetPort(uint32_t key_id, uint8_t value, int &msg_size)
Add a configuration value that is port-specific (MSGOUT messages).
Definition: ubx.cpp:509
bool sendMessage(const uint16_t msg, const uint8_t *payload, const uint16_t length)
Send a message.
Definition: ubx.cpp:1801
#define UBX_CFG_KEY_CFG_UART1OUTPROT_NMEA
Definition: ubx.h:226
#define UBX_MSG_CFG_TMODE3
Definition: ubx.h:139
ubx_payload_rx_mon_rf_t payload_rx_mon_rf
Definition: ubx.h:710
uint32_t sAcc
Speed accuracy estimate [mm/s].
Definition: ubx.h:391
#define UBX_CFG_KEY_CFG_UART1OUTPROT_RTCM3X
Definition: ubx.h:227
ubx_payload_rx_nav_sol_t payload_rx_nav_sol
Definition: ubx.h:699
int32_t velN
North velocity component [cm/s].
Definition: ubx.h:478
uint8_t day
Day of month, range 1..31 (UTC)
Definition: ubx.h:369
ubx_payload_rx_nav_pvt_t payload_rx_nav_pvt
Definition: ubx.h:697
#define UBX_CFG_KEY_CFG_UART1_STOPBITS
Definition: ubx.h:217
struct vehicle_gps_position_s * _gps_position
Definition: ubx.h:908
ubx_payload_rx_mon_ver_part1_t payload_rx_mon_ver_part1
Definition: ubx.h:711
uint32_t fnv1_32_str(uint8_t *str, uint32_t hval)
Calculate FNV1 hash.
Definition: ubx.cpp:1834
#define UBX_MSG_CFG_MSG
Definition: ubx.h:133
int32_t lat
Latitude [1e-7 deg].
Definition: ubx.h:324
#define UBX_SYNC2
Definition: ubx.h:57
ubx_payload_rx_mon_ver_part2_t payload_rx_mon_ver_part2
Definition: ubx.h:712
void reset()
reset the parsing state
Definition: rtcm.cpp:49
int8_t elev
Elevation [deg] range: +/-90.
Definition: ubx.h:449
#define UBX_CFG_KEY_NAVHPG_DGNSSMODE
Definition: ubx.h:257
int32_t lon
Longitude [1e-7 deg].
Definition: ubx.h:380
bool _got_velned
Definition: ubx.h:914
#define RTCM3_PREAMBLE
Definition: rtcm.h:39
uint8_t sec
Seconds of minute, range 0..60 (UTC)
Definition: ubx.h:412
#define UBX_CFG_KEY_CFG_SPIINPROT_NMEA
Definition: ubx.h:251
uint8_t numSvs
Number of Satellites.
Definition: ubx.h:440
int read(uint8_t *buf, int buf_length, int timeout)
read from device
Definition: gps_helper.h:206
#define MIN(X, Y)
Definition: ubx.cpp:66
uint16_t _ack_waiting_msg
Definition: ubx.h:923
#define UBX_MSG_ACK_ACK
Definition: ubx.h:131
virtual ~GPSDriverUBX()
Definition: ubx.cpp:95
uint8_t snr[20]
ubx_payload_rx_nav_sat_part1_t payload_rx_nav_sat_part1
Definition: ubx.h:704
#define UBX_CFG_KEY_NAVSPG_FIXMODE
Definition: ubx.h:259
OutputMode _output_mode
Definition: ubx.h:928
bool _got_posllh
Definition: ubx.h:913
#define UBX_CFG_KEY_SPI_MAXFF
Definition: ubx.h:297
hrt_abstime gps_abstime
Definition: definitions.h:58
#define UBX_CFG_KEY_CFG_USBOUTPROT_UBX
Definition: ubx.h:246
uint16_t inProtoMask
Definition: ubx.h:592
bool configureMessageRate(const uint16_t msg, const uint8_t rate)
Configure message rate.
Definition: ubx.cpp:1773
ubx_payload_tx_cfg_tmode3_t payload_tx_cfg_tmode3
Definition: ubx.h:721
#define UBX_TX_CFG_PRT_PORTID_USB
USB.
Definition: ubx.h:182
#define UBX_BAUDRATE_M8_AND_NEWER
baudrate for M8+ boards
Definition: ubx.h:192
uint16_t outProtoMask
Definition: ubx.h:593
#define UBX_TX_CFG_PRT_MODE
0b0000100011010000: 8N1
Definition: ubx.h:184
FixedPositionSettings fixed_position
Definition: base_station.h:107
int32_t height
Height above ellipsoid [mm].
Definition: ubx.h:382
#define UBX_CFG_KEY_TMODE_SVIN_MIN_DUR
Definition: ubx.h:281
#define UBX_CFG_KEY_CFG_UART1INPROT_UBX
Definition: ubx.h:222
#define UBX_MSG_NAV_TIMEUTC
Definition: ubx.h:121
#define UBX_TX_CFG_PRT_INPROTOMASK_GPS
RTCM3 in and UBX in.
Definition: ubx.h:187
#define UBX_MSG_RTCM3_1230
Definition: ubx.h:155
#define UBX_CFG_KEY_CFG_UART1INPROT_NMEA
Definition: ubx.h:223
gps_abstime _disable_cmd_last
Definition: ubx.h:922
void decodeInit(void)
Reset the parse state machine for a fresh start.
Definition: ubx.cpp:1739
#define UBX_CFG_KEY_CFG_USBINPROT_UBX
Definition: ubx.h:243
#define UBX_CFG_KEY_CFG_USBINPROT_RTCM3X
Definition: ubx.h:245
int receive(unsigned timeout) override
receive & handle new data from the device
Definition: ubx.cpp:713
bool _proto_ver_27_or_higher
true if protocol version 27 or higher detected
Definition: ubx.h:927
#define UBX_TX_CFG_NAV5_MASK
Only update dynamic model and fix mode.
Definition: ubx.h:204
int write(const void *buf, int buf_length)
write to the device
Definition: gps_helper.h:218
int reset(GPSRestartType restart_type) override
Reset GPS device.
Definition: ubx.cpp:1859
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
Definition: px4io.c:89
#define UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1087_I2C
Definition: ubx.h:291
#define UBX_MSG_MON_RF
Definition: ubx.h:145
#define UBX_TX_CFG_PRT_OUTPROTOMASK_RTCM
RTCM3 out and UBX out.
Definition: ubx.h:190
#define UBX_MSG_CFG_RATE
Definition: ubx.h:134
#define UBX_CFG_KEY_CFG_UART1INPROT_RTCM3X
Definition: ubx.h:224
uint32_t speed
Speed (3-D) [cm/s].
Definition: ubx.h:481
#define FNV1_32_INIT
Definition: ubx.cpp:69
#define UBX_TRACE_SVINFO(...)
Definition: ubx.cpp:76
#define UBX_RX_NAV_PVT_FLAGS_DIFFSOLN
diffSoln (1 if differential corrections were applied)
Definition: ubx.h:166
int32_t gSpeed
Ground Speed (2-D) [mm/s].
Definition: ubx.h:389
uint8_t valid
Validity flags (see UBX_RX_NAV_PVT_VALID_...)
Definition: ubx.h:373
int32_t nano
Fraction of second, range -1e9 .
Definition: ubx.h:406
uint8_t cno
Carrier to Noise Ratio (Signal Strength) [dbHz].
Definition: ubx.h:448
#define UBX_CFG_KEY_CFG_SPIINPROT_UBX
Definition: ubx.h:250
#define UBX_MSG_NAV_DOP
Definition: ubx.h:118
uint8_t min
Minute of hour, range 0..59 (UTC)
Definition: ubx.h:371
void gotRTCMMessage(uint8_t *buf, int buf_length)
got an RTCM message from the device
Definition: gps_helper.h:239
#define UBX_MSG_ACK_NAK
Definition: ubx.h:130
uint8_t _rate_count_vel
Definition: gps_helper.h:265
ubx_payload_rx_mon_rf_block_t block[1]
only read out the first block
Definition: ubx.h:553
#define UBX_RX_NAV_PVT_VALID_VALIDTIME
validTime (Valid UTC Time)
Definition: ubx.h:161
#define UBX_MSG_CFG_PRT
Definition: ubx.h:132
#define UBX_CFG_KEY_CFG_USBINPROT_NMEA
Definition: ubx.h:244
#define UBX_MSG_CFG_RST
Definition: ubx.h:137
int payloadRxAddNavSat(const uint8_t b)
Definition: ubx.cpp:1153
#define UBX_CFG_KEY_TMODE_SVIN_ACC_LIMIT
Definition: ubx.h:282
#define UBX_CFG_KEY_ODO_USE_COG
Definition: ubx.h:264
int32_t velD
NED down velocity [mm/s].
Definition: ubx.h:388
ubx_decode_state_t _decode_state
Definition: ubx.h:915
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
#define UBX_TX_CFG_PRT_PORTID
UART1.
Definition: ubx.h:181
#define UBX_CFG_KEY_TMODE_MODE
Definition: ubx.h:272
#define UBX_MSG_RTCM3_1077
Definition: ubx.h:147
int32_t velE
NED east velocity [mm/s].
Definition: ubx.h:387
#define UBX_TX_CFG_RST_BBR_MODE_COLD_START
Definition: ubx.h:211
uint8_t _rx_ck_b
Definition: ubx.h:921
ubx_payload_rx_nav_dop_t payload_rx_nav_dop
Definition: ubx.h:700
int(* GPSCallbackPtr)(GPSCallbackType type, void *data1, int data2, void *user)
Callback function for platform-specific stuff.
Definition: gps_helper.h:132
ubx_payload_tx_cfg_valset_t payload_tx_cfg_valset
Definition: ubx.h:723
#define GPS_EPOCH_SECS
Definition: gps_helper.h:145
#define UBX_MSG_INF_DEBUG
Definition: ubx.h:126
int payloadRxAddMonVer(const uint8_t b)
Add MON-VER payload rx byte.
Definition: ubx.cpp:1264
ubx_payload_rx_ack_ack_t payload_rx_ack_ack
Definition: ubx.h:713
#define UBX_CFG_KEY_CFG_SPIOUTPROT_NMEA
Definition: ubx.h:254
#define UBX_MSG_CFG_NAV5
Definition: ubx.h:136
GPSDriverUBX(Interface gpsInterface, GPSCallbackPtr callback, void *callback_user, struct vehicle_gps_position_s *gps_position, struct satellite_info_s *satellite_info, uint8_t dynamic_model=7)
Definition: ubx.cpp:82
#define UBX_CFG_KEY_CFG_USBOUTPROT_RTCM3X
Definition: ubx.h:248
bool _configured
Definition: ubx.h:911
uint8_t cfgData
configuration data (key and value pairs, max 64)
Definition: ubx.h:618
uint8_t sec
Seconds of minute, range 0..60 (UTC)
Definition: ubx.h:372
#define UBX_MSG_NAV_PVT
Definition: ubx.h:119
#define GPS_READ_BUFFER_SIZE
buffer size for the read() call. Messages can be longer than that.
Definition: gps_helper.h:46
#define UBX_CFG_KEY_CFG_UART1_DATABITS
Definition: ubx.h:218
int32_t velN
NED north velocity [mm/s].
Definition: ubx.h:386
U-Blox protocol definition.
#define UBX_TX_CFG_RATE_TIMEREF
0: UTC, 1: GPS time
Definition: ubx.h:199
#define UBX_CFG_KEY_TMODE_LAT_HP
Definition: ubx.h:277
request RTCM output. This is used for (fixed position) base stations
#define UBX_CFG_KEY_CFG_USBOUTPROT_NMEA
Definition: ubx.h:247
#define UBX_RX_NAV_PVT_VALID_VALIDDATE
validDate (Valid UTC Date)
Definition: ubx.h:160
RTCMParsing * _rtcm_parsing
Definition: ubx.h:930
#define UBX_CFG_KEY_TMODE_FIXED_POS_ACC
Definition: ubx.h:280
In cold start mode, the receiver has no information from the last position at startup.
#define UBX_RX_NAV_PVT_VALID_FULLYRESOLVED
fullyResolved (1 = UTC Time of Day has been fully resolved (no seconds uncertainty)) ...
Definition: ubx.h:162
#define UBX_TX_CFG_PRT_OUTPROTOMASK_GPS
UBX out.
Definition: ubx.h:189
uint8_t svid
Satellite ID.
Definition: ubx.h:427
#define UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1127_I2C
Definition: ubx.h:293
uint16_t year
Year (UTC)
Definition: ubx.h:367
struct satellite_info_s * _satellite_info
Definition: ubx.h:909
uint16_t vDOP
Vertical DOP [0.01].
Definition: ubx.h:337
#define UBX_MSG_RTCM3_1087
Definition: ubx.h:148
uint8_t svId
Satellite ID.
Definition: ubx.h:447
uint16_t _rx_payload_index
Definition: ubx.h:919
int8_t elev
Elevation [deg].
Definition: ubx.h:431
uint32_t baudRate
Definition: ubx.h:591
In warm start mode, the receiver has approximate information for time, position, and coarse satellite...
#define UBX_MSG_NAV_SOL
Definition: ubx.h:117
int parseChar(const uint8_t b)
Parse the binary UBX packet.
Definition: ubx.cpp:770
#define UBX_CFG_KEY_ODO_OUTLPVEL
Definition: ubx.h:265
uint8_t day
Day of month, range 1..31 (UTC)
Definition: ubx.h:409
#define UBX_MSG_RTCM3_1005
Definition: ubx.h:146
int32_t velD
Down velocity component [cm/s].
Definition: ubx.h:480
int32_t lon
Longitude [1e-7 deg].
Definition: ubx.h:323
#define UBX_WARN(...)
Definition: ubx.cpp:79
uint16_t noisePerMS
Noise level as measured by the GPS core.
Definition: ubx.h:543
#define UBX_TX_CFG_RST_MODE_SOFTWARE
Definition: ubx.h:213
int32_t hMSL
Height above mean sea level [mm].
Definition: ubx.h:383
#define UBX_TX_CFG_RATE_MEASINTERVAL
200ms for 5Hz (F9* boards use 10Hz)
Definition: ubx.h:197
Definition: ubx.h:696
bool _use_nav_pvt
Definition: ubx.h:926
uint16_t hDOP
Horizontal DOP [0.01].
Definition: ubx.h:338
uint32_t vAcc
Vertical accuracy estimate [mm].
Definition: ubx.h:385
uint16_t messageLength() const
Definition: rtcm.h:62
ubx_payload_tx_cfg_rate_t payload_tx_cfg_rate
Definition: ubx.h:716
ubx_rxmsg_state_t _rx_state
Definition: ubx.h:917
uint16_t measRate
Measurement Rate, GPS measurements are taken every measRate milliseconds.
Definition: ubx.h:600
uint8_t numSV
Number of SVs used in Nav Solution.
Definition: ubx.h:360
#define UBX_PACKET_TIMEOUT
Definition: ubx.cpp:63
#define UBX_SYNC1
Definition: ubx.h:56
int16_t azim
Azimuth [deg].
Definition: ubx.h:432
#define UBX_CFG_KEY_MSGOUT_UBX_NAV_PVT_I2C
Definition: ubx.h:288
int16_t azim
Azimuth [deg] range: 0-360.
Definition: ubx.h:450
uint8_t * message() const
Definition: rtcm.h:61
#define UBX_CFG_KEY_NAVSPG_DYNMODEL
Definition: ubx.h:261
uint8_t _rx_ck_a
Definition: ubx.h:920
GPS driver base class with Base Station Support.
Definition: base_station.h:49
int initCfgValset()
Init _buf as CFG-VALSET.
Definition: ubx.cpp:485
ubx_payload_rx_nav_svinfo_part1_t payload_rx_nav_svinfo_part1
Definition: ubx.h:702
int payloadRxDone(void)
Finish payload rx.
Definition: ubx.cpp:1332
#define UBX_MSG_MON_VER
Definition: ubx.h:144
int configureDevicePreV27()
Send configuration values and desired message rates (for protocol version < 27)
Definition: ubx.cpp:355
#define UBX_MSG_RTCM3_1097
Definition: ubx.h:152
#define UBX_MSG_NAV_SVINFO
Definition: ubx.h:122
#define UBX_CFG_KEY_TMODE_LON
Definition: ubx.h:275
uint32_t _ubx_version
Definition: ubx.h:925
int32_t lat
Latitude [1e-7 deg].
Definition: ubx.h:381
uint8_t _rate_count_lat_lon
Definition: gps_helper.h:264
#define UBX_TX_CFG_RST_BBR_MODE_HOT_START
Definition: ubx.h:209
#define UBX_MSG_NAV_POSLLH
Definition: ubx.h:116
BaseSettings _base_settings
Definition: base_station.h:110
#define UBX_CFG_KEY_MSGOUT_UBX_NAV_SAT_I2C
Definition: ubx.h:286
#define UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1097_I2C
Definition: ubx.h:292
#define UBX_CFG_KEY_CFG_UART1OUTPROT_UBX
Definition: ubx.h:225
#define UBX_CFG_KEY_MSGOUT_RTCM_3X_TYPE1077_I2C
Definition: ubx.h:290
int waitForAck(const uint16_t msg, const unsigned timeout, const bool report)
Wait for message acknowledge.
Definition: ubx.cpp:683
uint8_t numSV
Number of SVs used in Nav Solution.
Definition: ubx.h:379
#define UBX_CFG_KEY_TMODE_LON_HP
Definition: ubx.h:278
#define UBX_CFG_KEY_MSGOUT_UBX_NAV_DOP_I2C
Definition: ubx.h:287
uint8_t fixType
GNSSfix type: 0 = No fix, 1 = Dead Reckoning only, 2 = 2D fix, 3 = 3d-fix, 4 = GNSS + dead reckoning...
Definition: ubx.h:376
int payloadRxAddNavSvinfo(const uint8_t b)
Add NAV-SVINFO payload rx byte.
Definition: ubx.cpp:1208
#define UBX_TX_CFG_RATE_NAVRATE
cannot be changed
Definition: ubx.h:198
uint8_t month
Month, range 1..12 (UTC)
Definition: ubx.h:368
bool cfgValset(uint32_t key_id, T value, int &msg_size)
Add a configuration value to _buf and increase the message size msg_size as needed.
Definition: ubx.cpp:493
#define SWAP16(X)
Definition: ubx.cpp:67
#define UBX_RX_NAV_PVT_FLAGS_GNSSFIXOK
gnssFixOK (A valid fix (i.e within DOP & accuracy masks))
Definition: ubx.h:165
void calcChecksum(const uint8_t *buffer, const uint16_t length, ubx_checksum_t *checksum)
Calculate & add checksum for given buffer.
Definition: ubx.cpp:1764
int32_t nano
Fraction of second (UTC) [-1e9...1e9 ns].
Definition: ubx.h:375
#define UBX_CFG_KEY_ODO_OUTLPCOG
Definition: ubx.h:266
uint16_t _rx_payload_length
Definition: ubx.h:918
#define UBX_TX_CFG_PRT_MODE_SPI
Definition: ubx.h:185
#define UBX_CFG_KEY_ODO_USE_ODO
Definition: ubx.h:263
ubx_buf_t _buf
Definition: ubx.h:924
int payloadRxInit(void)
Start payload rx.
Definition: ubx.cpp:924
In hot start mode, the receiver was powered down only for a short time (4 hours or less)...
int configureDevice()
Send configuration values and desired message rates.
Definition: ubx.cpp:436
uint8_t flags
Fix Status Flags (see UBX_RX_NAV_PVT_FLAGS_...)
Definition: ubx.h:377
int activateRTCMOutput()
Definition: ubx.cpp:1674
int32_t headMot
Heading of motion (2-D) [1e-5 deg].
Definition: ubx.h:390
#define gps_absolute_time
Get the current time in us.
Definition: definitions.h:57
#define UBX_CFG_KEY_CFG_SPIOUTPROT_UBX
Definition: ubx.h:253
uint16_t _rx_msg
Definition: ubx.h:916
#define UBX_CFG_KEY_RATE_TIMEREF
Definition: ubx.h:270
normal GPS output
uint16_t length
Definition: ubx.h:311
#define UBX_MSG_INF_WARNING
Definition: ubx.h:129
uint8_t hour
Hour of day, range 0..23 (UTC)
Definition: ubx.h:410
uint8_t elevation[20]
ubx_ack_state_t _ack_state
Definition: ubx.h:912
#define UBX_TRACE_RXMSG(...)
Definition: ubx.cpp:75
#define UBX_CFG_KEY_CFG_SPIOUTPROT_RTCM3X
Definition: ubx.h:255
uint8_t cno
Carrier to Noise Ratio (Signal Strength) [dbHz].
Definition: ubx.h:430
uint8_t svid[20]
uint8_t hour
Hour of day, range 0..23 (UTC)
Definition: ubx.h:370
int32_t hMSL
Height above mean sea level [mm].
Definition: ubx.h:326
uint8_t layers
The layers where the configuration should be applied (.
Definition: ubx.h:616
#define UBX_CONFIG_TIMEOUT
Definition: ubx.cpp:62
#define UBX_MSG_NAV_VELNED
Definition: ubx.h:120
int payloadRxAdd(const uint8_t b)
Add payload rx byte.
Definition: ubx.cpp:1138
#define UBX_TX_CFG_PRT_PORTID_SPI
SPI.
Definition: ubx.h:183
int configure(unsigned &baudrate, OutputMode output_mode) override
configure the device
Definition: ubx.cpp:103
ubx_payload_rx_nav_sat_part2_t payload_rx_nav_sat_part2
Definition: ubx.h:705
int32_t velE
East velocity component [cm/s].
Definition: ubx.h:479
void setClock(timespec &t)
Definition: gps_helper.h:244
bool configureMessageRateAndAck(uint16_t msg, uint8_t rate, bool report_ack_error=false)
Combines the configure_message_rate & wait_for_ack calls.
Definition: ubx.cpp:1791
static void ECEF2lla(double ecef_x, double ecef_y, double ecef_z, double &latitude, double &longitude, float &altitude)
Convert an ECEF (Earth Centered Earth Fixed) coordinate to LLA WGS84 (Lat, Lon, Alt).
Definition: gps_helper.cpp:69
ubx_payload_rx_nav_velned_t payload_rx_nav_velned
Definition: ubx.h:707
uint32_t headAcc
Heading accuracy estimate (motion and vehicle) [1e-5 deg].
Definition: ubx.h:392
#define UBX_TRACE_PARSER(...)
Definition: ubx.cpp:74
uint8_t jamInd
CW jamming indicator, scaled (0=no CW jamming, 255=strong CW jamming)
Definition: ubx.h:545
bool addByte(uint8_t b)
add a byte to the message
Definition: rtcm.cpp:60
#define UBX_MSG_NAV_SAT
Definition: ubx.h:123
ubx_payload_rx_nav_svin_t payload_rx_nav_svin
Definition: ubx.h:706
#define UBX_MSG_CFG_VALSET
Definition: ubx.h:141
#define UBX_CFG_KEY_MSGOUT_UBX_NAV_SVIN_I2C
Definition: ubx.h:285
int32_t heading
Heading of motion 2-D [1e-5 deg].
Definition: ubx.h:483