PX4 Firmware
PX4 Autopilot Software http://px4.io
mtk.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 mtk.cpp
36  *
37  * @author Thomas Gubler <thomasgubler@student.ethz.ch>
38  * @author Julian Oes <julian@oes.ch>
39  */
40 
41 #include "mtk.h"
42 
43 #include <stdio.h>
44 #include <math.h>
45 #include <string.h>
46 #include <ctime>
47 #include <math.h>
48 
49 
50 GPSDriverMTK::GPSDriverMTK(GPSCallbackPtr callback, void *callback_user, struct vehicle_gps_position_s *gps_position) :
51  GPSHelper(callback, callback_user),
52  _gps_position(gps_position)
53 {
54  decodeInit();
55 }
56 
57 int
59 {
60  if (output_mode != OutputMode::GPS) {
61  GPS_WARN("MTK: Unsupported Output Mode %i", (int)output_mode);
62  return -1;
63  }
64 
65  if (baudrate > 0 && baudrate != MTK_BAUDRATE) {
66  return -1;
67  }
68 
69  /* set baudrate first */
71  return -1;
72  }
73 
74  baudrate = MTK_BAUDRATE;
75 
76  /* Write config messages, don't wait for an answer */
77  if (strlen(MTK_OUTPUT_5HZ) != write(MTK_OUTPUT_5HZ, strlen(MTK_OUTPUT_5HZ))) {
78  goto errout;
79  }
80 
81  gps_usleep(10000);
82 
83  if (strlen(MTK_SET_BINARY) != write(MTK_SET_BINARY, strlen(MTK_SET_BINARY))) {
84  goto errout;
85  }
86 
87  gps_usleep(10000);
88 
89  if (strlen(MTK_SBAS_ON) != write(MTK_SBAS_ON, strlen(MTK_SBAS_ON))) {
90  goto errout;
91  }
92 
93  gps_usleep(10000);
94 
95  if (strlen(MTK_WAAS_ON) != write(MTK_WAAS_ON, strlen(MTK_WAAS_ON))) {
96  goto errout;
97  }
98 
99  gps_usleep(10000);
100 
101  if (strlen(MTK_NAVTHRES_OFF) != write(MTK_NAVTHRES_OFF, strlen(MTK_NAVTHRES_OFF))) {
102  goto errout;
103  }
104 
105  return 0;
106 
107 errout:
108  GPS_WARN("mtk: config write failed");
109  return -1;
110 }
111 
112 int
113 GPSDriverMTK::receive(unsigned timeout)
114 {
115  uint8_t buf[GPS_READ_BUFFER_SIZE];
116  gps_mtk_packet_t packet{};
117 
118  /* timeout additional to poll */
119  gps_abstime time_started = gps_absolute_time();
120 
121  int j = 0;
122 
123  while (true) {
124 
125  int ret = read(buf, sizeof(buf), timeout);
126 
127  if (ret > 0) {
128  /* first read whatever is left */
129  if (j < ret) {
130  /* pass received bytes to the packet decoder */
131  while (j < ret) {
132  if (parseChar(buf[j], packet) > 0) {
133  handleMessage(packet);
134  return 1;
135  }
136 
137  j++;
138  }
139 
140  /* everything is read */
141  j = 0;
142  }
143 
144  } else {
145  gps_usleep(20000);
146  }
147 
148  /* in case we keep trying but only get crap from GPS */
149  if (time_started + timeout * 1000 < gps_absolute_time()) {
150  return -1;
151  }
152  }
153 }
154 
155 void
157 {
158  _rx_ck_a = 0;
159  _rx_ck_b = 0;
160  _rx_count = 0;
162 }
163 int
165 {
166  int ret = 0;
167 
169 
170  if (b == MTK_SYNC1_V16) {
172  _mtk_revision = 16;
173 
174  } else if (b == MTK_SYNC1_V19) {
176  _mtk_revision = 19;
177  }
178 
179  } else if (_decode_state == MTK_DECODE_GOT_CK_A) {
180  if (b == MTK_SYNC2) {
182 
183  } else {
184  // Second start symbol was wrong, reset state machine
185  decodeInit();
186  }
187 
188  } else if (_decode_state == MTK_DECODE_GOT_CK_B) {
189  // Add to checksum
190  if (_rx_count < 33) {
192  }
193 
194  // Fill packet buffer
195  ((uint8_t *)(&packet))[_rx_count] = b;
196  _rx_count++;
197 
198  /* Packet size minus checksum, XXX ? */
199  if (_rx_count >= sizeof(packet)) {
200  /* Compare checksum */
201  if (_rx_ck_a == packet.ck_a && _rx_ck_b == packet.ck_b) {
202  ret = 1;
203 
204  } else {
205  ret = -1;
206  }
207 
208  // Reset state machine to decode next packet
209  decodeInit();
210  }
211  }
212 
213  return ret;
214 }
215 
216 void
218 {
219  if (_mtk_revision == 16) {
220  _gps_position->lat = packet.latitude * 10; // from degrees*1e6 to degrees*1e7
221  _gps_position->lon = packet.longitude * 10; // from degrees*1e6 to degrees*1e7
222 
223  } else if (_mtk_revision == 19) {
224  _gps_position->lat = packet.latitude; // both degrees*1e7
225  _gps_position->lon = packet.longitude; // both degrees*1e7
226 
227  } else {
228  GPS_WARN("mtk: unknown revision");
229  _gps_position->lat = 0;
230  _gps_position->lon = 0;
231 
232  // Indicate this data is not usable and bail out
233  _gps_position->eph = 1000.0f;
234  _gps_position->epv = 1000.0f;
235  _gps_position->fix_type = 0;
236  return;
237  }
238 
239  _gps_position->alt = (int32_t)(packet.msl_altitude * 10); // from cm to mm
240  _gps_position->fix_type = packet.fix_type;
241  _gps_position->eph = packet.hdop / 100.0f; // from cm to m
242  _gps_position->epv = _gps_position->eph; // unknown in mtk custom mode, so we cheat with eph
243  _gps_position->hdop = packet.hdop / 100.0f;
245  _gps_position->vel_m_s = ((float)packet.ground_speed) / 100.0f; // from cm/s to m/s
246  _gps_position->cog_rad = ((float)packet.heading) * M_DEG_TO_RAD_F * 1e-2f; //from deg *100 to rad
248 
249  /* convert time and date information to unix timestamp */
250  struct tm timeinfo = {};
251  uint32_t timeinfo_conversion_temp;
252 
253  timeinfo.tm_mday = packet.date / 10000;
254  timeinfo_conversion_temp = packet.date - timeinfo.tm_mday * 10000;
255  timeinfo.tm_mon = (timeinfo_conversion_temp / 100) - 1;
256  timeinfo.tm_year = (timeinfo_conversion_temp - (timeinfo.tm_mon + 1) * 100) + 100;
257 
258  timeinfo.tm_hour = (packet.utc_time / 10000000);
259  timeinfo_conversion_temp = packet.utc_time - timeinfo.tm_hour * 10000000;
260  timeinfo.tm_min = timeinfo_conversion_temp / 100000;
261  timeinfo_conversion_temp -= timeinfo.tm_min * 100000;
262  timeinfo.tm_sec = timeinfo_conversion_temp / 1000;
263  timeinfo_conversion_temp -= timeinfo.tm_sec * 1000;
264 
265  timeinfo.tm_isdst = 0;
266 
267 #ifndef NO_MKTIME
268 
269  time_t epoch = mktime(&timeinfo);
270 
271  if (epoch > GPS_EPOCH_SECS) {
272  // FMUv2+ boards have a hardware RTC, but GPS helps us to configure it
273  // and control its drift. Since we rely on the HRT for our monotonic
274  // clock, updating it from time to time is safe.
275 
276  timespec ts{};
277  ts.tv_sec = epoch;
278  ts.tv_nsec = timeinfo_conversion_temp * 1000000ULL;
279 
280  setClock(ts);
281 
282  _gps_position->time_utc_usec = static_cast<uint64_t>(epoch) * 1000000ULL;
283  _gps_position->time_utc_usec += timeinfo_conversion_temp * 1000ULL;
284 
285  } else {
287  }
288 
289 #else
291 #endif
292 
295 
296  // Position and velocity update always at the same time
297  _rate_count_vel++;
299 }
300 
301 void
303 {
304  _rx_ck_a = _rx_ck_a + b;
306 }
#define MTK_SYNC2
Definition: mtk.h:48
#define GPS_WARN(...)
Definition: definitions.h:48
int receive(unsigned timeout) override
receive & handle new data from the device
Definition: mtk.cpp:113
#define MTK_SET_BINARY
Definition: mtk.h:51
int setBaudrate(int baudrate)
set the Baudrate
Definition: gps_helper.h:228
int32_t longitude
Longitude in degrees * 10^7.
Definition: mtk.h:71
#define gps_usleep
Definition: definitions.h:51
void handleMessage(gps_mtk_packet_t &packet)
Handle the package once it has arrived.
Definition: mtk.cpp:217
uint32_t ground_speed
velocity in m/s
Definition: mtk.h:73
uint32_t utc_time
Definition: mtk.h:78
int read(uint8_t *buf, int buf_length, int timeout)
read from device
Definition: gps_helper.h:206
hrt_abstime gps_abstime
Definition: definitions.h:58
#define MTK_BAUDRATE
Definition: mtk.h:57
int configure(unsigned &baudrate, OutputMode output_mode) override
configure the device
Definition: mtk.cpp:58
uint8_t _rx_ck_a
Definition: mtk.h:122
void decodeInit()
Reset the parse state machine for a fresh start.
Definition: mtk.cpp:156
int write(const void *buf, int buf_length)
write to the device
Definition: gps_helper.h:218
unsigned _rx_count
Definition: mtk.h:121
#define MTK_SYNC1_V16
Definition: mtk.h:46
uint8_t _rx_ck_b
Definition: mtk.h:123
uint8_t ck_b
Definition: mtk.h:81
uint8_t ck_a
Definition: mtk.h:80
#define MTK_SYNC1_V19
Definition: mtk.h:47
uint8_t _rate_count_vel
Definition: gps_helper.h:265
struct vehicle_gps_position_s * _gps_position
Definition: mtk.h:118
int32_t latitude
Latitude in degrees * 10^7.
Definition: mtk.h:70
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
uint8_t _mtk_revision
Definition: mtk.h:120
#define GPS_EPOCH_SECS
Definition: gps_helper.h:145
uint32_t date
Definition: mtk.h:77
#define GPS_READ_BUFFER_SIZE
buffer size for the read() call. Messages can be longer than that.
Definition: gps_helper.h:46
#define MTK_NAVTHRES_OFF
Definition: mtk.h:54
uint8_t fix_type
fix type: XXX correct for that
Definition: mtk.h:76
GPSDriverMTK(GPSCallbackPtr callback, void *callback_user, struct vehicle_gps_position_s *gps_position)
Definition: mtk.cpp:50
uint8_t satellites
number of satellites used
Definition: mtk.h:75
#define MTK_WAAS_ON
Definition: mtk.h:53
#define MTK_OUTPUT_5HZ
Definition: mtk.h:50
int32_t heading
heading in degrees * 10^2
Definition: mtk.h:74
uint32_t msl_altitude
MSL altitude in meters * 10^2.
Definition: mtk.h:72
#define MTK_SBAS_ON
Definition: mtk.h:52
uint16_t hdop
horizontal dilution of position (without unit)
Definition: mtk.h:79
int parseChar(uint8_t b, gps_mtk_packet_t &packet)
Parse the binary MTK packet.
Definition: mtk.cpp:164
uint8_t _rate_count_lat_lon
Definition: gps_helper.h:264
the structures of the binary packets
Definition: mtk.h:68
#define gps_absolute_time
Get the current time in us.
Definition: definitions.h:57
normal GPS output
void setClock(timespec &t)
Definition: gps_helper.h:244
mtk_decode_state_t _decode_state
Definition: mtk.h:119
void addByteToChecksum(uint8_t)
While parsing add every byte (except the sync bytes) to the checksum.
Definition: mtk.cpp:302