PX4 Firmware
PX4 Autopilot Software http://px4.io
sbf.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2018 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 sbf.cpp
36  *
37  * Septentrio protocol as defined in PPSDK SBF Reference Guide 4.1.8
38  *
39  * @author Matej Frančeškin <Matej.Franceskin@gmail.com>
40  *
41 */
42 
43 #include "sbf.h"
44 #include <string.h>
45 #include <math.h>
46 
47 #define SBF_CONFIG_TIMEOUT 500 // ms, timeout for waiting ACK
48 #define SBF_PACKET_TIMEOUT 2 // ms, if now data during this delay assume that full update received
49 #define DISABLE_MSG_INTERVAL 1000000 // us, try to disable message with this interval
50 
51 /**** Trace macros, disable for production builds */
52 #define SBF_TRACE_PARSER(...) {/*GPS_INFO(__VA_ARGS__);*/} /* decoding progress in parse_char() */
53 #define SBF_TRACE_RXMSG(...) {/*GPS_INFO(__VA_ARGS__);*/} /* Rx msgs in payload_rx_done() */
54 
55 /**** Warning macros, disable to save memory */
56 #define SBF_WARN(...) {GPS_WARN(__VA_ARGS__);}
57 #define SBF_DEBUG(...) {/*GPS_WARN(__VA_ARGS__);*/}
58 
59 GPSDriverSBF::GPSDriverSBF(GPSCallbackPtr callback, void *callback_user,
60  struct vehicle_gps_position_s *gps_position,
61  struct satellite_info_s *satellite_info,
62  uint8_t dynamic_model)
63  : GPSBaseStationSupport(callback, callback_user)
64  , _gps_position(gps_position)
65  , _satellite_info(satellite_info)
66  , _dynamic_model(dynamic_model)
67 {
68  decodeInit();
69 }
70 
72 {
73 }
74 
75 int
77 {
78  _configured = false;
79 
81  baudrate = SBF_TX_CFG_PRT_BAUDRATE;
82 
83  _output_mode = output_mode;
84 
85  if (output_mode != OutputMode::RTCM) {
87  }
88 
89  // Change the baudrate
90  char msg[64];
91  snprintf(msg, sizeof(msg), SBF_CONFIG_BAUDRATE, baudrate);
92 
93  if (!sendMessage(msg)) {
94  return -1; // connection and/or baudrate detection failed
95  }
96 
97  /* flush input and wait for at least 50 ms silence */
98  decodeInit();
99  receive(50);
100  decodeInit();
101 
103  return -1; // connection and/or baudrate detection failed
104  }
105 
106  // at this point we have correct baudrate on both ends
107 
108  const char *config_cmds;
109 
111  config_cmds = SBF_CONFIG_RTCM;
112 
113  } else {
114 
115  if (_dynamic_model < 6) {
116  snprintf(msg, sizeof(msg), SBF_CONFIG_RECEIVER_DYNAMICS, "low");
117 
118  } else if (_dynamic_model < 7) {
119  snprintf(msg, sizeof(msg), SBF_CONFIG_RECEIVER_DYNAMICS, "moderate");
120 
121  } else if (_dynamic_model < 8) {
122  snprintf(msg, sizeof(msg), SBF_CONFIG_RECEIVER_DYNAMICS, "high");
123 
124  } else {
125  snprintf(msg, sizeof(msg), SBF_CONFIG_RECEIVER_DYNAMICS, "max");
126  }
127 
129 
130  config_cmds = SBF_CONFIG;
131  }
132 
133  uint8_t i = 0;
134  msg[0] = 0;
135 
136  while (*config_cmds != 0) {
137  msg[i] = *config_cmds;
138 
139  if (msg[i++] == '\n') {
140  msg[i] = 0;
141 
143 
144  i = 0;
145  msg[0] = 0;
146  }
147 
148  config_cmds++;
149  }
150 
153  snprintf(msg, sizeof(msg), SBF_CONFIG_RTCM_STATIC_COORDINATES,
156  static_cast<double>(_base_settings.settings.fixed_position.altitude));
158  snprintf(msg, sizeof(msg), SBF_CONFIG_RTCM_STATIC_OFFSET, 0.0, 0.0, 0.0);
162  }
163  }
164 
165  _configured = true;
166  return 0;
167 }
168 
169 bool
171 {
172  SBF_DEBUG("Send MSG: %s", msg);
173 
174  // Send message
175  int length = static_cast<int>(strlen(msg));
176 
177  return (write(msg, length) == length);
178 }
179 
180 bool
181 GPSDriverSBF::sendMessageAndWaitForAck(const char *msg, const int timeout)
182 {
183  SBF_DEBUG("Send MSG: %s", msg);
184 
185  // Send message
186  int length = static_cast<int>(strlen(msg));
187 
188  if (write(msg, length) != length) {
189  return false;
190  }
191 
192  // Wait for acknowledge
193  // For all valid set -, get - and exe -commands, the first line of the reply is an exact copy
194  // of the command as entered by the user, preceded with "$R:"
195  char buf[GPS_READ_BUFFER_SIZE];
196  size_t offset = 1;
197  gps_abstime time_started = gps_absolute_time();
198 
199  bool found_response = false;
200 
201  do {
202  --offset; //overwrite the null-char
203  int ret = read(reinterpret_cast<uint8_t *>(buf) + offset, sizeof(buf) - offset - 1, timeout);
204 
205  if (ret < 0) {
206  // something went wrong when polling or reading
207  SBF_WARN("sbf poll_or_read err");
208  return false;
209  }
210 
211  offset += ret;
212  buf[offset++] = '\0';
213 
214  if (!found_response && strstr(buf, "$R: ") != nullptr) {
215  SBF_DEBUG("READ %d: %s", (int)offset, buf);
216  found_response = true;
217  }
218 
219  if (offset >= sizeof(buf)) {
220  offset = 1;
221  }
222 
223  } while (time_started + 1000 * timeout > gps_absolute_time());
224 
225  return found_response;
226 }
227 
228 int // -1 = error, 0 = no message handled, 1 = message handled, 2 = sat info message handled
229 GPSDriverSBF::receive(unsigned timeout)
230 {
231  // Do not receive messages until we're configured
232  if (!_configured) {
233  gps_usleep(timeout * 1000);
234  return 0;
235  }
236 
237  uint8_t buf[GPS_READ_BUFFER_SIZE];
238 
239  // timeout additional to poll
240  gps_abstime time_started = gps_absolute_time();
241 
242  int handled = 0;
243 
244  while (true) {
245  // Wait for only SBF_PACKET_TIMEOUT if something already received.
246  int ret = read(buf, sizeof(buf), handled ? SBF_PACKET_TIMEOUT : timeout);
247 
248  if (ret < 0) {
249  // something went wrong when polling or reading
250  SBF_WARN("ubx poll_or_read err");
251  return -1;
252 
253  } else {
254  // SBF_DEBUG("Read %d bytes", ret);
255 
256  // pass received bytes to the packet decoder
257  for (int i = 0; i < ret; i++) {
258  handled |= parseChar(buf[i]);
259  // SBF_DEBUG("parsed %d: 0x%x", i, buf[i]);
260  }
261  }
262 
263  if (handled > 0) {
264  return handled;
265  }
266 
267  // abort after timeout if no useful packets received
268  if (time_started + timeout * 1000 < gps_absolute_time()) {
269  SBF_DEBUG("timed out, returning");
270  return -1;
271  }
272  }
273 }
274 
275 int // 0 = decoding, 1 = message handled, 2 = sat info message handled
276 GPSDriverSBF::parseChar(const uint8_t b)
277 {
278  int ret = 0;
279 
280  switch (_decode_state) {
281 
282  // Expecting Sync1
283  case SBF_DECODE_SYNC1:
284  if (b == SBF_SYNC1) { // Sync1 found --> expecting Sync2
285  SBF_TRACE_PARSER("A");
286  ret = payloadRxAdd(b); // add a payload byte
288 
289  } else if (b == RTCM3_PREAMBLE && _rtcm_parsing) {
290  SBF_TRACE_PARSER("RTCM");
293  }
294 
295  break;
296 
297  // Expecting Sync2
298  case SBF_DECODE_SYNC2:
299  if (b == SBF_SYNC2) { // Sync2 found --> expecting CRC
300  SBF_TRACE_PARSER("B");
301  ret = payloadRxAdd(b); // add a payload byte
303 
304  } else { // Sync1 not followed by Sync2: reset parser
305  decodeInit();
306  }
307 
308  break;
309 
310  // Expecting payload
311  case SBF_DECODE_PAYLOAD:
312  SBF_TRACE_PARSER(".");
313 
314  ret = payloadRxAdd(b); // add a payload byte
315 
316  if (ret < 0) {
317  // payload not handled, discard message
318  ret = 0;
319  decodeInit();
320 
321  } else if (ret > 0) {
322  ret = payloadRxDone(); // finish payload processing
323  decodeInit();
324 
325  } else {
326  // expecting more payload, stay in state SBF_DECODE_PAYLOAD
327  ret = 0;
328 
329  }
330 
331  break;
332 
333  case SBF_DECODE_RTCM3:
334  if (_rtcm_parsing->addByte(b)) {
335  SBF_DEBUG("got RTCM message with length %i", (int)_rtcm_parsing->messageLength());
337  decodeInit();
338  }
339 
340  break;
341  }
342 
343  return ret;
344 }
345 
346 /**
347  * Add payload rx byte
348  */
349 int // -1 = error, 0 = ok, 1 = payload completed
351 {
352  int ret = 0;
353  uint8_t *p_buf = reinterpret_cast<uint8_t *>(&_buf);
354 
355  p_buf[_rx_payload_index++] = b;
356 
357  if ((_rx_payload_index > 7 && _rx_payload_index >= _buf.length) || _rx_payload_index >= sizeof(_buf)) {
358  ret = 1; // payload received completely
359  }
360 
361  return ret;
362 }
363 
364 /**
365  * Calculate buffer CRC16
366  */
367 uint16_t
368 crc16(const uint8_t *data_p, uint32_t length)
369 {
370  uint8_t x;
371  uint16_t crc = 0;
372 
373  while (length--) {
374  x = crc >> 8 ^ *data_p++;
375  x ^= x >> 4;
376  crc = static_cast<uint16_t>((crc << 8) ^ (x << 12) ^ (x << 5) ^ x);
377  }
378 
379  return crc;
380 }
381 
382 /**
383  * Finish payload rx
384  */
385 int // 0 = no message handled, 1 = message handled, 2 = sat info message handled
387 {
388  int ret = 0;
389  struct tm timeinfo;
390  time_t epoch;
391 
392  if (_buf.length <= 4 || _buf.crc16 != crc16(reinterpret_cast<uint8_t *>(&_buf) + 4, _buf.length - 4)) {
393  return 1;
394  }
395 
396  // handle message
397  switch (_buf.msg_id) {
398  case SBF_ID_PVTGeodetic:
399  SBF_TRACE_RXMSG("Rx PVTGeodetic");
400  _msg_status |= 1;
401 
403  _gps_position->fix_type = 1;
404 
405  } else if (_buf.payload_pvt_geodetic.mode_type == 6) {
406  _gps_position->fix_type = 4;
407 
409  _gps_position->fix_type = 5;
410 
412  _gps_position->fix_type = 6;
413 
414  } else {
415  _gps_position->fix_type = 3;
416  }
417 
418  // Check fix and error code
420 
421  // Check boundaries and invalidate GPS velocities
422  // We're not just checking for the do-not-use value (-2*10^10) but for any value beyond the specified max values
423  if (fabsf(_buf.payload_pvt_geodetic.vn) > 600.0f || fabsf(_buf.payload_pvt_geodetic.ve) > 600.0f ||
424  fabsf(_buf.payload_pvt_geodetic.vu) > 600.0f) {
425  _gps_position->vel_ned_valid = false;
426  }
427 
428  // Check boundaries and invalidate position
429  // We're not just checking for the do-not-use value (-2*10^10) but for any value beyond the specified max values
430  if (fabs(_buf.payload_pvt_geodetic.latitude) > M_PI_2 || fabs(_buf.payload_pvt_geodetic.longitude) > M_PI_2 ||
431  fabs(_buf.payload_pvt_geodetic.height) > 100000.0 || fabs(_buf.payload_pvt_geodetic.undulation) > 100000.0) {
432  _gps_position->fix_type = 0;
433  }
434 
435  if (_buf.payload_pvt_geodetic.nr_sv < 255) { // 255 = do not use value
437 
438  if (_satellite_info) {
439  // Only fill in the satellite count for now (we could use the ChannelStatus message for the
440  // other data, but it's really large: >800B)
443  ret = 2;
444  }
445 
446  } else {
448  }
449 
450  _gps_position->lat = static_cast<int>(round(_buf.payload_pvt_geodetic.latitude * M_RAD_TO_DEG * 1e7));
451  _gps_position->lon = static_cast<int>(round(_buf.payload_pvt_geodetic.longitude * M_RAD_TO_DEG * 1e7));
452  _gps_position->alt_ellipsoid = static_cast<int>(round(_buf.payload_pvt_geodetic.height * 1000));
453  _gps_position->alt = static_cast<int>(round((_buf.payload_pvt_geodetic.height - static_cast<double>
455 
456  /* H and V accuracy are reported in 2DRMS, but based off the uBlox reporting we expect RMS.
457  * Devide by 100 from cm to m and in addition divide by 2 to get RMS. */
458  _gps_position->eph = static_cast<float>(_buf.payload_pvt_geodetic.h_accuracy) / 200.0f;
459  _gps_position->epv = static_cast<float>(_buf.payload_pvt_geodetic.v_accuracy) / 200.0f;
460 
461  _gps_position->vel_n_m_s = static_cast<float>(_buf.payload_pvt_geodetic.vn);
462  _gps_position->vel_e_m_s = static_cast<float>(_buf.payload_pvt_geodetic.ve);
463  _gps_position->vel_d_m_s = -1.0f * static_cast<float>(_buf.payload_pvt_geodetic.vu);
466 
467  _gps_position->cog_rad = static_cast<float>(_buf.payload_pvt_geodetic.cog) * M_DEG_TO_RAD_F;
468  _gps_position->c_variance_rad = 1.0f * M_DEG_TO_RAD_F;
469 
470  // _buf.payload_pvt_geodetic.cog is set to -2*10^10 for velocities below 0.1m/s
471  if (_buf.payload_pvt_geodetic.cog > 360.0f) {
473  }
474 
476 #ifndef NO_MKTIME
477  /* convert to unix timestamp */
478  memset(&timeinfo, 0, sizeof(timeinfo));
479 
480  timeinfo.tm_year = 1980 - 1900;
481  timeinfo.tm_mon = 0;
482  timeinfo.tm_mday = 6 + _buf.WNc * 7;
483  timeinfo.tm_hour = 0;
484  timeinfo.tm_min = 0;
485  timeinfo.tm_sec = _buf.TOW / 1000;
486 
487  epoch = mktime(&timeinfo);
488 
489  if (epoch > GPS_EPOCH_SECS) {
490  // FMUv2+ boards have a hardware RTC, but GPS helps us to configure it
491  // and control its drift. Since we rely on the HRT for our monotonic
492  // clock, updating it from time to time is safe.
493 
494  timespec ts;
495  memset(&ts, 0, sizeof(ts));
496  ts.tv_sec = epoch;
497  ts.tv_nsec = (_buf.TOW % 1000) * 1000 * 1000;
498  setClock(ts);
499 
500  _gps_position->time_utc_usec = static_cast<uint64_t>(epoch) * 1000000ULL;
501  _gps_position->time_utc_usec += (_buf.TOW % 1000) * 1000;
502  }
503 
504 #endif
507  _rate_count_vel++;
509  ret |= (_msg_status == 7) ? 1 : 0;
510  break;
511 
513  SBF_TRACE_RXMSG("Rx VelCovGeodetic");
514  _msg_status |= 2;
516 
519  }
520 
523  }
524 
525  break;
526 
527  case SBF_ID_DOP:
528  SBF_TRACE_RXMSG("Rx DOP");
529  _msg_status |= 4;
532  break;
533 
534  default:
535  break;
536  }
537 
538  if (ret > 0) {
540  }
541 
542  if (ret == 1) {
543  _msg_status &= ~1;
544  }
545 
546  return ret;
547 }
548 
549 void
551 {
553  _rx_payload_index = 0;
554 
556  if (!_rtcm_parsing) {
557  _rtcm_parsing = new RTCMParsing();
558  }
559 
560  _rtcm_parsing->reset();
561  }
562 }
563 
564 int
566 {
567  bool res = false;
568 
569  switch (restart_type) {
570  case GPSRestartType::Hot:
572  break;
573 
576  break;
577 
580  break;
581 
582  default:
583  break;
584  }
585 
586  return (res) ? 0 : -2;
587 }
int parseChar(const uint8_t b)
Parse the binary SBF packet.
Definition: sbf.cpp:276
#define SBF_ID_PVTGeodetic
Definition: sbf.h:112
#define SBF_CONFIG_RTCM
Definition: sbf.h:73
float cog
Course over ground: this is defined as the angle of the vehicle with respect to the local level North...
Definition: sbf.h:156
#define SBF_CONFIG_RTCM_STATIC_OFFSET
Definition: sbf.h:95
#define SBF_PACKET_TIMEOUT
Definition: sbf.cpp:48
union GPSBaseStationSupport::BaseSettings::@4 settings
GPSDriverSBF(GPSCallbackPtr callback, void *callback_user, struct vehicle_gps_position_s *gps_position, struct satellite_info_s *satellite_info, uint8_t dynamic_model)
Definition: sbf.cpp:59
virtual ~GPSDriverSBF() override
Definition: sbf.cpp:71
RTCMParsing * _rtcm_parsing
Definition: sbf.h:366
GPSRestartType
Definition: gps_helper.h:101
int setBaudrate(int baudrate)
set the Baudrate
Definition: gps_helper.h:228
float ve
Velocity in the East direction.
Definition: sbf.h:154
#define gps_usleep
Definition: definitions.h:51
#define SBF_CONFIG_TIMEOUT
Definition: sbf.cpp:47
int configure(unsigned &baudrate, OutputMode output_mode) override
Definition: sbf.cpp:76
bool sendMessageAndWaitForAck(const char *msg, const int timeout)
Send a message and waits for acknowledge.
Definition: sbf.cpp:181
#define SBF_DEBUG(...)
Definition: sbf.cpp:57
void reset()
reset the parsing state
Definition: rtcm.cpp:49
#define RTCM3_PREAMBLE
Definition: rtcm.h:39
int read(uint8_t *buf, int buf_length, int timeout)
read from device
Definition: gps_helper.h:206
uint16_t _rx_payload_index
Definition: sbf.h:363
hrt_abstime gps_abstime
Definition: definitions.h:58
uint8_t error
PVT error code.
Definition: sbf.h:135
FixedPositionSettings fixed_position
Definition: base_station.h:107
#define SBF_CONFIG
Definition: sbf.h:60
#define SBF_CONFIG_BAUDRATE
Definition: sbf.h:52
double height
Marker ellipsoidal height (with respect to the ellipsoid specified by Datum)
Definition: sbf.h:150
int write(const void *buf, int buf_length)
write to the device
Definition: gps_helper.h:218
#define SBF_CONFIG_RTCM_STATIC_COORDINATES
Definition: sbf.h:92
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
Definition: px4io.c:89
bool _configured
Definition: sbf.h:360
#define SBF_ID_DOP
Definition: sbf.h:111
int payloadRxAdd(const uint8_t b)
Add payload rx byte.
Definition: sbf.cpp:350
uint8_t mode_type
Bit field indicating the PVT mode type, as follows: 0: No PVT available (the Error field indicates th...
Definition: sbf.h:120
void gotRTCMMessage(uint8_t *buf, int buf_length)
got an RTCM message from the device
Definition: gps_helper.h:239
uint16_t vDOP
Definition: sbf.h:251
uint8_t _rate_count_vel
Definition: gps_helper.h:265
float vn
Velocity in the North direction.
Definition: sbf.h:153
#define SBF_ID_VelCovGeodetic
Definition: sbf.h:114
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
int(* GPSCallbackPtr)(GPSCallbackType type, void *data1, int data2, void *user)
Callback function for platform-specific stuff.
Definition: gps_helper.h:132
#define SBF_CONFIG_RESET_HOT
Definition: sbf.h:98
#define GPS_EPOCH_SECS
Definition: gps_helper.h:145
double latitude
Marker latitude, from −π/2 to +π/2, positive North of Equator.
Definition: sbf.h:148
#define SBF_SYNC2
Definition: sbf.h:108
struct vehicle_gps_position_s * _gps_position
Definition: sbf.h:356
uint16_t hDOP
Definition: sbf.h:250
#define SBF_CONFIG_RESET_WARM
Definition: sbf.h:101
#define GPS_READ_BUFFER_SIZE
buffer size for the read() call. Messages can be longer than that.
Definition: gps_helper.h:46
uint16_t crc16(const uint8_t *data_p, uint32_t length)
Calculate buffer CRC16.
Definition: sbf.cpp:368
request RTCM output. This is used for (fixed position) base stations
#define SBF_TRACE_PARSER(...)
Definition: sbf.cpp:52
uint16_t length
block revision number, starting from 0 at the initial block definition, and incrementing each time ba...
Definition: sbf.h:279
double longitude
Marker longitude, from −π to +π, positive East of Greenwich.
Definition: sbf.h:149
In cold start mode, the receiver has no information from the last position at startup.
#define SBF_TRACE_RXMSG(...)
Definition: sbf.cpp:53
float cov_ve_ve
Variance of the east-velocity estimate.
Definition: sbf.h:234
In warm start mode, the receiver has approximate information for time, position, and coarse satellite...
int reset(GPSRestartType restart_type) override
Reset GPS device.
Definition: sbf.cpp:565
#define SBF_SYNC1
Definition: sbf.h:107
uint16_t messageLength() const
Definition: rtcm.h:62
uint32_t TOW
The Length field is a 2-byte unsigned integer containing the size of the SBF block.
Definition: sbf.h:282
#define SBF_CONFIG_RTCM_STATIC2
Definition: sbf.h:89
uint8_t * message() const
Definition: rtcm.h:61
int payloadRxDone(void)
Finish payload rx.
Definition: sbf.cpp:386
GPS driver base class with Base Station Support.
Definition: base_station.h:49
uint16_t msg_id
The CRC field is the 16-bit CRC of all the bytes in an SBF block from and including the ID field to t...
Definition: sbf.h:275
void decodeInit(void)
Reset the parse state machine for a fresh start.
Definition: sbf.cpp:550
#define SBF_TX_CFG_PRT_BAUDRATE
Definition: sbf.h:58
sbf_decode_state_t _decode_state
Definition: sbf.h:362
#define SBF_CONFIG_RTCM_STATIC1
Definition: sbf.h:86
uint8_t _rate_count_lat_lon
Definition: gps_helper.h:264
sbf_buf_t _buf
Definition: sbf.h:364
float undulation
Geoid undulation computed from the global geoid model defined in the document ’Technical Characteris...
Definition: sbf.h:151
uint16_t WNc
The GPS week number associated with the TOW.
Definition: sbf.h:284
uint64_t _last_timestamp_time
Definition: sbf.h:359
BaseSettings _base_settings
Definition: base_station.h:110
uint8_t nr_sv
Total number of satellites used in the PVT computation.
Definition: sbf.h:176
#define SBF_CONFIG_FORCE_INPUT
Definition: sbf.h:50
struct satellite_info_s * _satellite_info
Definition: sbf.h:357
int receive(unsigned timeout) override
receive & handle new data from the device
Definition: sbf.cpp:229
bool sendMessage(const char *msg)
Send a message.
Definition: sbf.cpp:170
#define SBF_CONFIG_RESET
Definition: sbf.h:54
#define SBF_CONFIG_RECEIVER_DYNAMICS
Definition: sbf.h:56
In hot start mode, the receiver was powered down only for a short time (4 hours or less)...
#define gps_absolute_time
Get the current time in us.
Definition: definitions.h:57
sbf_payload_vel_cov_geodetic_t payload_vel_col_geodetic
Definition: sbf.h:290
sbf_payload_pvt_geodetic_t payload_pvt_geodetic
Definition: sbf.h:289
uint8_t _msg_status
Definition: sbf.h:361
#define SBF_CONFIG_RESET_COLD
Definition: sbf.h:104
float cov_vn_vn
Variance of the north-velocity estimate.
Definition: sbf.h:233
Septentrio protocol as defined in PPSDK SBF Reference Guide 4.1.8.
void setClock(timespec &t)
Definition: gps_helper.h:244
float vu
Velocity in the Up direction.
Definition: sbf.h:155
sbf_payload_dop_t payload_dop
Definition: sbf.h:291
bool addByte(uint8_t b)
add a byte to the message
Definition: rtcm.cpp:60
float cov_vu_vu
Variance of the up - velocity estimate.
Definition: sbf.h:235
uint16_t crc16
The Sync field is a 2-byte array always set to 0x24, 0x40.
Definition: sbf.h:270
uint8_t _dynamic_model
Definition: sbf.h:358
OutputMode _output_mode
Definition: sbf.h:365
#define SBF_WARN(...)
Definition: sbf.cpp:56