1 /*
2
3 Track reader for "Dell Axim Navigation System" GPB files,
4
5 Copyright (C) 2006 Olaf Klein, o.b.klein@gpsbabel.org
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
21 */
22
23 #include <ctype.h>
24 #include <math.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "defs.h"
29
30 #define MYNAME "axim_gpb"
31
32 #define RECORD_LEN 344
33
34 static gbfile* fin;
35
36 static
37 arglist_t axim_gpb_args[] = {
38 ARG_TERMINATOR
39 };
40
41 static float
le_read32_float(const void * src)42 le_read32_float(const void* src)
43 {
44 float f;
45 int32_t i;
46
47 i = le_read32(src);
48 memcpy(&f, &i, 4);
49
50 return f;
51 }
52
53 static void
decode_buff(const char * buff,route_head * track)54 decode_buff(const char* buff, route_head* track)
55 {
56 struct tm tm;
57 double lat, lon, alt, dir;
58 float vdop, hdop, pdop, spd, Uf1;
59 int sats;
60 waypoint* wpt;
61
62 wpt = waypt_new();
63
64 memset(&tm, '\0', sizeof(tm));
65
66 tm.tm_year = le_read16((void*)(buff + 16));
67 tm.tm_mon = le_read16((void*)(buff + 18));
68 tm.tm_mday = le_read16((void*)(buff + 22));
69 tm.tm_hour = le_read16((void*)(buff + 24));
70 tm.tm_min = le_read16((void*)(buff + 26));
71 tm.tm_sec = le_read16((void*)(buff + 28));
72 lat = le_read_double((void*)(buff + 32));
73 lon = le_read_double((void*)(buff + 40));
74 spd = le_read32_float((void*)(buff + 48));
75 dir = le_read32_float((void*)(buff + 52));
76
77 alt = le_read32_float((void*)(buff + 64));
78 Uf1 = le_read32_float((void*)(buff + 68));
79
80 hdop = le_read32_float((void*)(buff + 84));
81 vdop = le_read32_float((void*)(buff + 88));
82 pdop = le_read32_float((void*)(buff + 92));
83 sats = le_read16((void*)(buff + 96));
84
85 wpt->latitude = lat;
86 wpt->longitude = lon;
87 wpt->altitude = alt;
88 #if 0
89 /* These values can be, but must not be right. */
90 /* Further checks are needed to verify that. */
91 /* (!!! reference data !!!) */
92 WAYPT_SET(wpt, course, dir);
93 wpt->hdop = hdop;
94 wpt->vdop = vdop;
95 wpt->pdop = pdop;
96 wpt->sat = sats;
97 WAYPT_SET(wpt, speed, spd * 10);
98 #endif
99 /* We don't have a header with some magic fixed numbers or strings. */
100 /* So let us check the range for some basic values */
101
102 is_fatal(
103 (tm.tm_year < 2005) ||
104 (tm.tm_mon < 1) || (tm.tm_mon > 12) ||
105 (tm.tm_mday < 1) || (tm.tm_mday > 31) ||
106 (tm.tm_hour > 23) || (tm.tm_min > 60) || (tm.tm_sec > 60),
107 MYNAME ": Invalid or unsupported file (invalid time-stamp).");
108 is_fatal(
109 (fabs(wpt->latitude) > 90) ||
110 (fabs(wpt->longitude) > 180),
111 MYNAME ": Invalid or unsupported file (lat or/and lon out of range).");
112
113 /* post work */
114
115 tm.tm_year-=1900;
116 tm.tm_mon--;
117 wpt->SetCreationTime(mkgmtime(&tm));
118
119 track_add_wpt(track, wpt);
120 }
121
122 /*******************************************************************************
123 * %%% global callbacks called by gpsbabel main process %%% *
124 *******************************************************************************/
125
126 static void
axim_gpb_rd_init(const char * fname)127 axim_gpb_rd_init(const char* fname)
128 {
129 fin = gbfopen(fname, "rb", MYNAME);
130 }
131
132 static void
axim_gpb_rd_deinit(void)133 axim_gpb_rd_deinit(void)
134 {
135 gbfclose(fin);
136 }
137
138 static void
axim_gpb_read(void)139 axim_gpb_read(void)
140 {
141 char buff[RECORD_LEN];
142 route_head* track = NULL;
143 size_t bytes;
144
145 while ((bytes = gbfread(buff, 1, RECORD_LEN, fin))) {
146 is_fatal((bytes != RECORD_LEN), MYNAME ": Invalid or unsupported file (filesize).");
147 if (track == NULL) {
148 track = route_head_alloc();
149 track_add_head(track);
150 }
151 decode_buff(buff, track);
152 }
153 }
154
155 /**************************************************************************/
156
157 ff_vecs_t axim_gpb_vecs = {
158 ff_type_file,
159 {
160 ff_cap_none /* waypoints */,
161 ff_cap_read /* tracks */,
162 ff_cap_none /* routes */,
163 },
164 axim_gpb_rd_init,
165 NULL,
166 axim_gpb_rd_deinit,
167 NULL,
168 axim_gpb_read,
169 NULL,
170 NULL,
171 axim_gpb_args,
172 CET_CHARSET_ASCII, 0
173 };
174 /**************************************************************************/
175