1 /*
2     Global data for GPSBabel.
3 
4     Copyright (C) 2012-2016, Zingo Andersen zingo@zingo.org
5     Copyright (C) 2016 Robert Lipe, robertlipe+source@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  * This is the bridge between the GPSBabel and globalsat sport devices
24  * gh625XT. Globalsat has a few devices under the sport brand and they
25  * are using a similar USB serial protocol.
26  * Currently only gh625XT is supported by this driver but the code could
27  * extended (maybe autodetect) support more devices in the future.
28  *
29  * The code is based on GH625XT-COMMUNICATION_SPECS_20111205-1.pdf from Globasat
30  * that they nicely supplied on request.
31  *
32  * Usage examples:
33  * gpsbabel -i globalsat -f /dev/ttyUSB0 -o gpx,garminextensions -F xxx.gpx
34  * gpsbabel -i globalsat -f /dev/ttyUSB0 -o gtrnctr,course=0,sport=Running -F xxx.fit
35  *
36  */
37 #ifndef GLOBALSATSPORT_H_INCLUDED_
38 #define GLOBALSATSPORT_H_INCLUDED_
39 
40 #include <cstdint>           // for uint32_t, uint8_t, uint16_t, int16_t
41 
42 #include <QtCore/QString>    // for QString
43 #include <QtCore/QTimeZone>  // for QTimeZone
44 #include <QtCore/QVector>    // for QVector
45 
46 #include "defs.h"
47 #include "format.h"          // for Format
48 #include "gbfile.h"          // for gbfclose, gbfopen, gbfread, gbfwrite, gbfile
49 
50 
51 class GlobalsatSportFormat : public Format
52 {
53 public:
get_args()54   QVector<arglist_t>* get_args() override
55   {
56     return &globalsat_args;
57   }
58 
get_type()59   ff_type get_type() const override
60   {
61     return ff_type_serial;
62   }
63 
get_cap()64   QVector<ff_cap> get_cap() const override
65   {
66     return {
67       ff_cap_none,			// waypoints
68       ff_cap_read,			// tracks
69       ff_cap_none,			// routes
70     };
71   }
72 
get_encode()73   QString get_encode() const override
74   {
75     return CET_CHARSET_ASCII;
76   }
77 
get_fixed_encode()78   int get_fixed_encode() const override
79   {
80     return 0;
81   }
82 
83   void rd_init(const QString& fname) override;
84   void read() override;
85   void rd_deinit() override;
86 
87 private:
88   /* Types */
89   enum globalsat_commands_e {
90     CommandWhoAmI = 0xBF,
91     CommandGetSystemInformation = 0x85,
92     CommandGetSystemConfiguration = 0x86,
93 
94     CommandSetSystemConfiguration = 0x96,
95     CommandSetSystemInformation = 0x98,
96     CommandGetScreenshot = 0x83,
97 
98     CommandGetWaypoints = 0x77,
99     CommandSendWaypoint = 0x76,
100     CommandDeleteWaypoints = 0x75,
101 
102     CommandSendRoute = 0x93,
103     CommandDeleteAllRoutes = 0x97,
104 
105     CommandGetTrackFileHeaders = 0x78,
106     CommandGetTrackFileSections = 0x80,
107     CommandGetNextTrackSection = 0x81,
108     //CommandReGetLastSection = 0x82,
109     CommandId_FINISH = 0x8A,
110     CommandSendTrackStart = 0x90,
111     CommandSendTrackSection = 0x91,
112 
113     HeaderTypeLaps = 0xAA,
114     HeaderTypeTrackPoints = 0x55,
115 
116     ResponseInsufficientMemory = 0x95,
117     ResponseResendTrackSection = 0x92,
118     ResponseSendTrackFinish = 0x9A
119   };
120 
121   struct gh_date {
122     uint8_t Year;
123     uint8_t Month;
124     uint8_t Day;
125   };
126 
127   struct gh_time {
128     uint8_t Hour;
129     uint8_t Minute;
130     uint8_t Second;
131   };
132 
133   struct gh_trainheader {
134     gh_date dateStart;
135     gh_time timeStart;
136     uint32_t TotalPoint;		//6-9
137     uint32_t TotalTime;		//10-13
138     uint32_t TotalDistance;	//14-17
139     uint16_t LapCnts;		//18-19
140     union {
141       uint32_t Index;
142       uint32_t StartPt;
143     } gh_ptrec;			//20-23
144     union {
145       uint32_t LapIndex;
146       uint32_t EndPt;
147     } gh_laprec;			//24-27
148     uint8_t DataType;		//28
149   };
150 
151   struct gh_db_train {
152     gh_date dateStart;
153     gh_time timeStart;
154     uint32_t TotalPoint;		//6-9
155     uint32_t TotalTime;		//10-13
156     uint32_t TotalDistance;	//14-17
157     uint16_t LapCnts;		//18-19
158     union {
159       uint32_t Index;
160       uint32_t StartPt;
161     } gh_ptrec;			//20-23
162     union {
163       uint32_t LapIndex;
164       uint32_t EndPt;
165     } gh_laprec;			//24-27
166     uint8_t MultiSport;		//28 on/off
167     uint16_t Calory;		//29-30
168     uint32_t MaxSpeed;
169     uint8_t MaxHeart;
170     uint8_t AvgHeart;
171 
172     uint16_t Ascent;
173     uint16_t Descent;
174 
175     int16_t MinAlti;
176     int16_t MaxAlti;
177     uint16_t AvgCadns;
178     uint16_t BestCadns;
179     uint16_t AvgPower;
180     uint16_t MaxPower;
181     uint8_t Sport1;
182     uint8_t Sport2;
183     uint8_t Sport3;
184     uint8_t Sport4;
185     uint8_t Sport5;
186   };
187 
188   struct gh_db_lap {
189     uint32_t AccruedTime;
190     uint32_t TotalTime;
191     uint32_t TotalDistance;
192     uint16_t Calory;
193     uint32_t MaxSpeed;
194     uint8_t MaxHeart;
195     uint8_t AvgHeart;
196     int16_t MinAlti;
197     int16_t MaxAlti;
198     uint16_t AvgCadns;
199     uint16_t BestCadns;
200     uint16_t AvgPower;
201     uint16_t MaxPower;
202     uint8_t MultiSportIndex;
203     uint32_t StartPt;
204     uint32_t EndPt;
205   };
206 
207   struct gh_recpoint {
208     uint32_t Latitude;
209     uint32_t Longitude;
210     int16_t Altitude;
211     uint32_t Speed;
212     uint8_t HeartRate;
213     uint32_t IntervalTime;
214     uint16_t Cadence;
215     uint16_t PwrCadence;
216     uint16_t Power;
217   };
218 
219   /* Member Functions */
220 
221   void serial_init(const char* fname);
222   void serial_deinit();
223   int serial_recv_byte() const;
224   void serial_write_byte(uint8_t byte) const;
225   int recv_byte();
226   void write_byte(uint8_t byte);
227   void globalsat_write_package(uint8_t* payload, uint32_t size);
228   uint8_t* globalsat_read_package(int* out_length, uint8_t* out_DeviceCommand);
229   void globalsat_send_simple(uint8_t command);
230   void globalsat_probe_device();
231   void waypoint_read();
232   void track_read();
233   static void route_read();
234 
235   /* Data Members */
236 
237   void* serial_handle{nullptr};
238   bool isSizeSwapped{false};
239 
240   char* showlist{nullptr};               // if true show a list instead of download tracks
241   char* track{nullptr};                  // if not 0 only download this track, if 0 download all
242 
243   char* opt_dump_file{nullptr};          // dump raw data to this file (optional)
244   char* opt_input_dump_file{nullptr};    // if true input is from a dump-file instead of serial console
245   char* opt_timezone{nullptr};
246   gbfile* dumpfile{nullptr};             // used for creating bin/RAW datadump files, useful for testing
247   gbfile* in_file{nullptr};              // used for reading from bin/RAW datadump files, useful for testing
248   QTimeZone* timezn{nullptr};
249 
250   QVector<arglist_t> globalsat_args = {
251     {"showlist", &showlist, "list tracks", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr},
252     {"track", &track, "get track", "0", ARGTYPE_INT, ARG_NOMINMAX, nullptr},
253     {"dump-file", &opt_dump_file, "Dump raw data to this file", nullptr, ARGTYPE_OUTFILE, ARG_NOMINMAX, nullptr},
254     {"input-is-dump-file", &opt_input_dump_file, "Dump raw data to this file", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr},
255     {"timezone", &opt_timezone, "Time zone ID", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr},
256   };
257 };
258 #endif // GPX_H_INCLUDED_
259