OpenCPN Partial API docs
Loading...
Searching...
No Matches
garmin_wrapper.cpp
Go to the documentation of this file.
1/*
2 Garmin Jeeps - OpenCPN Interface Wrapper.
3
4 Copyright (C) 2010 David S Register
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <https://www.gnu.org/licenses/>.
18 */
19
27#include "config.h"
28
29#include "model/garmin_wrapper.h"
30
31#include "gpsapp.h"
32#include "garmin_gps.h"
33#include "gpsserial.h"
34
35#define GPS_DEBUG
36
37static gpsdevh *my_gps_devh;
38
39wxString GetLastGarminError() {
40 return wxString(GetDeviceLastError(), wxConvUTF8);
41}
42
43/*
44 Verify and force port closure after every called routine.
45 This is necessary for aborts in Windows environment, since ports cannot be
46 multiply opened.
47*/
48
49/* Wrapped interface from higher level objects */
50int Garmin_GPS_Init(const wxString &port_name) {
51 int ret;
52 GPS_Enable_Error();
53 GPS_Enable_Warning();
54 GPS_Enable_User();
55 GPS_Enable_Diagnose();
56 char m[1];
57 m[0] = '\0';
58
59 GPS_Error(m);
60
61 ret = GPS_Init(port_name.mb_str());
62 VerifyPortClosed();
63
64 return ret;
65}
66
67int Garmin_GPS_Open(wxString &port_name) {
68 return GPS_Init(port_name.mb_str());
69}
70
71int Garmin_GPS_PVT_On(wxString &port_name) {
72 return Garmin_Serial_GPS_PVT_On(port_name.mb_str());
73}
74
75int Garmin_GPS_PVT_Off(wxString &port_name) {
76 return Garmin_Serial_GPS_PVT_Off(port_name.mb_str());
77}
78
79int Garmin_GPS_GetPVT(void *pvt) {
80 return GPS_Serial_Command_Pvt_Get((GPS_PPvt_Data *)pvt);
81}
82
83void Garmin_GPS_ClosePortVerify() { VerifyPortClosed(); }
84
85wxString Garmin_GPS_GetSaveString() {
86 return wxString(gps_save_string, wxConvUTF8);
87}
88
89void Garmin_GPS_PrepareWptData(GPS_PWay pway, RoutePoint *prp) {
90 pway->lat = prp->m_lat;
91 pway->lon = prp->m_lon;
92 pway->alt_is_unknown = 1;
93 pway->alt = 0.0;
94 strncpy(pway->ident, (prp->GetName().Truncate(6)).mb_str(), 6);
95}
96
97int Garmin_GPS_SendWaypoints(const wxString &port_name,
98 RoutePointList *wplist) {
99 int ret_val = 0;
100
101 int nPoints = wplist->size();
102
103 // Create the array of GPS_PWays
104
105 GPS_SWay **ppway = (GPS_SWay **)malloc(nPoints * sizeof(GPS_PWay));
106
107 // and the GPS_Oways themselves
108 for (int i = 0; i < nPoints; i++) ppway[i] = GPS_Way_New();
109
110 // Now fill in the useful elements
111 for (int i = 0; i < nPoints; i++) {
112 GPS_PWay pway = ppway[i];
113 auto it = wplist->begin() + i;
114 RoutePoint *prp = *it;
115
116 Garmin_GPS_PrepareWptData(pway, prp);
117 }
118
119 // Transmit the list to the GPS receiver
120 int xfer_result = GPS_Command_Send_Waypoint(
121 port_name.mb_str(), ppway, nPoints, 0 /*int (*cb)(GPS_PWay *)*/);
122 ret_val = xfer_result;
123
124 // Free all the memory
125 for (int i = 0; i < nPoints; i++) GPS_Way_Del(&ppway[i]);
126
127 free(ppway);
128
129 VerifyPortClosed();
130 return ret_val;
131}
132
133// This routine creates an array of waypoint structures for an A200 route
134// transfer according to the "Garmin GPS Interface Specification" page 20.
135// The returned array contains the following packets:
136//
137// route header packet
138// waypoint packet
139// ...
140// waypoint packet
141//
142// The total number of elements in the array (route header packet and
143// all waypoint packets) is returned in the "size" argument.
144
145GPS_SWay **Garmin_GPS_Create_A200_Route(Route *pr, int route_number,
146 int *size) {
147 RoutePointList *wplist = pr->pRoutePointList;
148 int nPoints = wplist->size();
149
150 // Create the array of GPS_PWays
151 // There will be one extra for the route header
152
153 *size = nPoints + 1;
154
155 GPS_SWay **ppway = (GPS_SWay **)malloc((*size) * sizeof(GPS_PWay));
156
157 // and the GPS_Oways themselves
158 for (int i = 0; i < nPoints + 1; i++) ppway[i] = GPS_Way_New();
159
160 // Now fill in the useful elements
161
162 // Element 0 is a route record
163
164 GPS_PWay pway = ppway[0];
165 pway->isrte = true;
166 pway->rte_num = route_number;
167 strncpy(pway->rte_ident, (pr->m_RouteNameString.Truncate(255)).mb_str(), 255);
168 strncpy(pway->rte_cmnt, (pr->m_RouteNameString.Truncate(19)).mb_str(), 19);
169
170 // Elements 1..n are waypoints
171 for (int i = 1; i < *size; i++) {
172 GPS_PWay pway = ppway[i];
173 auto it = wplist->begin() + i;
174 RoutePoint *prp = *it;
175
176 Garmin_GPS_PrepareWptData(pway, prp);
177 }
178
179 return ppway;
180}
181
182// This routine creates an array of waypoint structures for an A201 route
183// transfer according to the "Garmin GPS Interface Specification" page 21.
184// The returned array contains the following packets:
185//
186// route header packet
187// waypoint packet
188// link packet
189// waypoint packet
190// link packet
191// ...
192// waypoint packet
193//
194// The total number of elements in the array (route header packet, link
195// packets and waypoint packets) is returned in the "size" argument.
196
197GPS_SWay **Garmin_GPS_Create_A201_Route(Route *pr, int route_number,
198 int *size) {
199 RoutePointList *wplist = pr->pRoutePointList;
200 int nPoints = wplist->size();
201
202 // Create the array of GPS_PWays
203 // There will be one for the route header, n for each way point
204 // and n-1 for each link
205
206 *size = 1 + nPoints + (nPoints - 1);
207
208 GPS_SWay **ppway = (GPS_SWay **)malloc((*size) * sizeof(GPS_PWay));
209
210 // and the GPS_Oways themselves
211 for (int i = 0; i < *size; i++) ppway[i] = GPS_Way_New();
212
213 // Now fill in the useful elements
214
215 // Element 0 is a route record
216
217 GPS_PWay pway = ppway[0];
218 pway->isrte = true;
219 pway->rte_num = route_number;
220 strncpy(pway->rte_ident, (pr->m_RouteNameString.Truncate(255)).mb_str(), 255);
221 strncpy(pway->rte_cmnt, (pr->m_RouteNameString.Truncate(19)).mb_str(), 19);
222
223 // Odd elements 1,3,5... are waypoints
224 // Even elements 2,4,6... are links
225 for (int i = 1; i < *size; i++) {
226 if (i % 2 == 1) /* Odd */
227 {
228 GPS_PWay pway = ppway[i];
229 auto it = wplist->begin() + i;
230 RoutePoint *prp = *it;
231
232 Garmin_GPS_PrepareWptData(pway, prp);
233 } else /* Even */
234 {
235 /* Apparently, 0 filled links are OK */
236 GPS_PWay pway = ppway[i];
237 pway->islink = true;
238 pway->rte_link_class = 0;
239 memset(pway->rte_link_subclass, 0, sizeof(pway->rte_link_subclass));
240 memset(pway->rte_link_ident, 0, sizeof(pway->rte_link_ident));
241 }
242 }
243
244 return ppway;
245}
246
247int Garmin_GPS_SendRoute(const wxString &port_name, Route *pr,
248 N0183DlgCtx dlg_ctx) {
249 int ret_val = 0;
250
251 int route_number = 1;
252
253 // If the device supports unique numbered waypoints,
254 // Then we must query the device to find an empty number
255 if ((gps_rte_hdr_type == pD200) || (gps_rte_hdr_type == pD201)) {
256 // Retrieve <ALL> routes from the device
257 GPS_Diag("Garmin: trying to get free route number");
258 GPS_PWay *pprouteway;
259 int32 npacks = GPS_A200_Get(port_name.mb_str(), &pprouteway);
260 if (npacks < 0) return npacks;
261 dlg_ctx.set_value(40);
262
263 // Iterate on the packets, finding the first route number from [0..9] that
264 // is not present
265
266 // An array of route numbers, set element to true as encountered
267 bool brn[10];
268 for (int i = 0; i < 10; i++) brn[i] = false;
269
270 for (int ip = 0; ip < npacks; ip++) {
271 GPS_PWay pway = pprouteway[ip];
272 if (pway->isrte) {
273 if ((pway->rte_num < 10)) brn[pway->rte_num] = true;
274 }
275 }
276
277 // Find the first candidate within [1..9] that is unused
278 bool bfound_empty = false;
279 for (int i = 1; i < 10; i++) {
280 if (brn[i] == false) {
281 route_number = i;
282 bfound_empty = true;
283 break;
284 }
285 }
286 GPS_Diag("Using route number: %d", route_number);
287
288 // Ask the user if it is all right to overwrite
289 if (!bfound_empty) {
290 if (!dlg_ctx.confirm_overwrite()) {
291 return 0;
292 }
293 }
294 }
295
296 // Based on the route transfer protocol create the array of transfer packets
297 GPS_SWay **ppway;
298 int elements = 0;
299 if (gps_route_transfer == pA201)
300 ppway = Garmin_GPS_Create_A201_Route(pr, route_number, &elements);
301 else
302 ppway = Garmin_GPS_Create_A200_Route(pr, route_number, &elements);
303
304 // Transmit the Route to the GPS receiver
305 int xfer_result = GPS_Command_Send_Route(port_name.mb_str(), ppway, elements);
306 ret_val = xfer_result;
307
308 // Free all the memory
309 for (int i = 0; i < elements; i++) GPS_Way_Del(&ppway[i]);
310
311 free(ppway);
312 dlg_ctx.set_value(80);
313
314 VerifyPortClosed();
315 return ret_val;
316}
317
318/*
319int Garmin_USB_On()
320{
321 int ret_val = GPS_Device_On("usb:", &my_gps_devh);
322
323 return ret_val;
324}
325
326int Garmin_USB_Off()
327{
328 int ret_val = GPS_Device_Off(my_gps_devh);
329
330 return ret_val;
331}
332*/
Represents a waypoint or mark within the navigation system.
Definition route_point.h:71
Represents a navigational route in the navigation system.
Definition route.h:99
RoutePointList * pRoutePointList
Ordered list of waypoints (RoutePoints) that make up this route.
Definition route.h:336
wxString m_RouteNameString
User-assigned name for the route.
Definition route.h:247