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