Original document : Michael Hofmann
Updates : Jorgen van der Velde
Internals
Debugging
First, install the necessary software to get the GPS tracker working on Windows (drivers and @trip PC from the mobile action website). Restart your PC, then play around with the GPS tracker, try to record some points, and make sure you can actually read them into @trip PC. Close @trip PC and disconnect the tracker.
A marvelous tool to monitor the serial port communication is portmon. Unfortunatelly it does not work under Windows 7, so I use it on a virtual machine under Windows XP. Set “Edit->Max Output Bytes” to 4096, select “Options->Show Hex”, and choose the correct com port for the tracker in “Capture->Ports”.
Attach the GPS tracker to the PC, start @trip PC and download the complete data on the tracker.
Another tool that comes in handy is Hercules. It is a free serial terminal program. You can use a hex editor to create strings or files containing the command sequence. Use Hercules to send the file to the device, recording the response. Right click the main window to set the view to hexadecimal.
GPSD support
For gpsd support, try the navman kernel driver to get an USB serial device at something like /dev/ttyUSB0. Do this before you plug the device in:
—-
sudo modprobe navman echo -n "0x0df7 0x0900" | sudo tee /sys/bus/usb-serial/drivers/navman/new_id
—-
and then plug your device in. You now have read-only access to the device and you can use it as an nmea data source for gpsd.
USB transport
The i-gotU GT-120 has a vendor id of 0x0df7 and a product id of 0x0900.
Data can be read from interrupt endpoint 0x81 with sth. like
—-
usb_interrupt_read(handle, 0x81, buf, size, timeout);
—-
Writes are done with control messages:
—-
usb_control_msg(handle, 0x21, 0x09, 0x0200, 0x0000, data, size, timeout);
—-
This must be done asynchronously, i.e., writes should be independent from reads. If one read completes, the next one must be started immediately.
There seems to be a firmware bug that may send responses twice for some commands. If the transmission is done synchronously, it will not be possible to detect and discard superfluous bytes. This is especially important on Mac OS X, as the USB interrupt transfers there ignore the timeout given.
Binary protocol
Commands and responses
Communication takes place via a command-response exchange: the PC sends a command, the device sends a response.
The commands consists of 16 bytes. On the GT-120 the commands may be sent as two 8 byte chunks or one 16 byte chunk. On the GT-800, 820 and 900 it must be sent as one 16 byte chunk.
The GPS acknowledges the commands by sending a response. The older types (GT-120) send two response blocks: after the first 8 bytes an empty response block (containing no data) is sent. After the second 8 bytes chunk a second response block is sent. This one might contain data. Later types (GT-800+) only send the second response block and ommit the first empty one.
The last byte of all commands contains a checksum (SS) so that the lsb of the sum of all command bytes is zero. Before each command, the connection is cleared, i.e., all superfluous bytes that are still in the input buffer are discarded.
The responses are at least three bytes long and may contain data. Responses don’t have a checksum.
—-
Response:
Data: 93 XX XX YY YY YY …
XX: big endian data size (≥ 0) or error code (< 0):
FFFE: seems to be a recoverable error
YY: optional data.
—-
A special block is an empty block: XX XX is 0x0000, not YY YY bytes
General commands
NmeaSwitchCommand:
Command chunk 1: 93 01 01 XX 00 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 00
XX:
00 GPS Dongle mode (NMEA)
01 GPS Tracer mode (normal trackpoint recording)
03 GPS Configure mode (no NMEA)
Note: when a GT-120 for example is attached to the USB port, it starts sending NMEA strings (Dongle mode). It must be set to mode 03 using this command in order to communicate with the device. Though later types (GT-800+) support this command, it appears not to have any meaning, since these devices don’t have a NMEA Dongle Mode.
IdentificationCommand
Command chunk 1: 93 0A 00 00 00 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 0A XX XX XX XX YY ZZ MM MM UU UU
XX: little endian serial number
YY: major version number
ZZ: minor version number (00-99)
MM: model number (01 for GT100/GT120, 02 for GT200, 08 for GT-800)?
UU: USB library version
CountCommand (number of data points)
Command chunk 1: 93 0B 03 00 1D 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 03 XX XX XX
XX: big endian number of data points
Internal memory read? (used for number of datapoints)
Command chunk 1: 93 0B XX YY YY 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 XX ZZ…
XX: read size
YY: big endian read position
ZZ: read data
ModelCommand
Command chunk 1: 93 05 04 00 03 01 9F 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 03 XX XX YY
XX: always C220?
YY: 0x13 for GT-100, 0x14 for GT-120, 0x15 for GT-200, 0x17 for GT-800 (pro), GT-900 (pro)
Internal memory read? (used for model type)
Command chunk 1: 93 05 04 XX XX 01 9F 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 XX XX YY…
XX: read size
YY: read data
Flash read commands
ReadCommand
Command chunk 1: 93 05 07 XX XX 04 03 YY
Response: 93 00 00
Command chunk 2: YY YY 00 00 00 00 00 SS
Response: 93 XX XX ZZ…
XX: big endian read size (1000 for read, 0010 for purge)
YY: big endian read position
ZZ read data
Flash erase commands
UnknownWriteCommand1
Command chunk 1: 93 06 04 00 XX 01 06 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 00
XX: 00 for purge, 01? for write
WriteCommand
Command chunk 1: 93 06 07 XX XX 04 WW YY
Response: 93 00 00
Command chunk 2: YY YY 00 00 00 00 00 SS
Response: 93 00 00
Data chunk n: ZZ ZZ ZZ ZZ ZZ ZZ ZZ SS
Response: 93 00 00
WW: 20 for purge, 02 for write
XX: big endian write size (0000 for purge, 0100 for write)
YY: big endian write position
ZZ: write data
needs ceil(size / 7) data chunks
UnknownWriteCommand2
Command chunk 1: 93 05 04 XX XX 01 05 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 XX XX ZZ
XX: big endian read size (0001 for purge and write)
ZZ: purge first time 03, purge second time and write 00
UnknownPurgeCommand1
Command chunk 1: 93 0C 00 XX 00 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 00
XX: first time called 1E, second time called 1F
UnknownPurgeCommand2
Command chunk 1: 93 08 02 00 00 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 00
Other commands
Command used after write (not tested)
Command chunk 1: 93 06 04 00 01 01 06 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 00
BC4 off mode
Command chunk 1: 93 01 XX 04 HH MM LL 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 00
XX:
01 log time = 0
04 log time > 0
HH, MM, LL: logtime (seconds)?
Unknown command (GT-800)
Command chunk 1: 93 10 00 00 00 00 00 00
Response: 93 00 00
Command chunk 2: 00 00 00 00 00 00 00 SS
Response: 93 00 1A … Probably the GPS time in 0.1 s units
Startup @trip
GT-800 Pro, Firmware 7.11, GT-800, Firmware 6.05, @trip PC 3.5 Build 1110.630 (Oct 6 2011)
NmeaSwitchCommand(03) ReadCommand(0x000000, 0x1000) ModelCommand() IdentificationCommand() Unknown command (GT-800) CountCommand ReadCommand(0x000000, 0x1000)
Purging (erasing flash memory)
@trip PC reads the first 0x10 bytes of each block starting from the end of the flash (0x0FF000 or 0x1FF000) and stops at the first block where these bytes are not 0xFF. Each block but the first one is then purged according to the following pseudo code:
GT-100, Firmware 1.39, @trip PC 2.0 908.446
purge = false blocks = 0x080 for i = blocks - 1; i > 0; --i: if purge: while UnknownWriteCommand2(0x0001) != 0x00: pass else: if ReadCommand(i * 0x1000, 0x10) != rep(0xff, 0x10): purge = true else: continue UnknownWriteCommand1(0x00) writeCommand(0x20, i * 0x1000, '') if purge: UnknownPurgeCommand2() while UnknownWriteCommand2(0x0001) != 0x00: pass UnknownPurgeCommand2()
GT-200, Firmware 2.11, @trip PC 1.0 804.0976
purge = false blocks = 0x100 for i = blocks - 1; i > 0; --i: if purge: while UnknownWriteCommand2(0x0001) != 0x00: pass else: if ReadCommand(i * 0x1000, 0x10) != rep(0xff, 0x10): purge = true else: continue UnknownWriteCommand1(0x00) WriteCommand(0x20, i * 0x1000, '') if purge: UnknownPurgeCommand2() while UnknownWriteCommand2(0x0001) != 0x00: pass
GT-200, Firmware 2.11, @trip PC 2.0 811.2582
purge = false blocks = 0x100 for i = blocks - 1; i > 0; --i: if purge: while UnknownWriteCommand2(0x0001) != 0x00: pass else: if ReadCommand(i * 0x1000, 0x10) != rep(0xff, 0x10): purge = true else: continue UnknownWriteCommand1(0x00) WriteCommand(0x20, i * 0x1000, '') if purge: UnknownPurgeCommand2() while UnknownWriteCommand2(0x0001) != 0x00: pass UnknownPurgeCommand2()
GT-100, Firmware 2.24, @trip PC 2.0 908.446
purge = false blocks = 0x080 for i = blocks - 1; i > 0; --i: if purge: while UnknownWriteCommand2(0x0001) != 0x00: pass else: if ReadCommand(i * 0x1000, 0x10) != rep(0xff, 0x10): purge = true else: continue UnknownWriteCommand1(0x00) WriteCommand(0x20, i * 0x1000, '') if purge: UnknownPurgeCommand1(0x1e) UnknownPurgeCommand1(0x1f) while UnknownWriteCommand2(0x0001) != 0x00: pass UnknownPurgeCommand1(0x1e) UnknownPurgeCommand1(0x1f)
GT-120, Firmware 3.03, @trip PC 2.0 811.2582
purge = false blocks = 0x200 for i = blocks - 1; i > 0; --i: if purge: while UnknownWriteCommand2(0x0001) != 0x00: pass else: if ReadCommand(i * 0x1000, 0x10) != rep(0xff, 0x10): purge = true else: continue UnknownWriteCommand1(0x00) WriteCommand(0x20, i * 0x1000, '') if purge: UnknownPurgeCommand1(0x1e) UnknownPurgeCommand1(0x1f) while UnknownWriteCommand2(0x0001) != 0x00: pass UnknownPurgeCommand1(0x1e) UnknownPurgeCommand1(0x1f)
GT-800 Pro, Firmware 7.11, GT-800 Pro, Firmware 6.05 @trip PC 3.5 Build 1110.630 (Oct 6 2011)
purge = false blocks = 0x700 for i = blocks - 1; i > 0; --i: if !purge: if ReadCommand(XX = (i * 0x1000), YY=0x10) != rep(0xff, 0x10): purge = true else: continue UnknownWriteCommand1(XX=0x00) WriteCommand(XX=0x0000, WW=0x20, YY = (i * 0x1000)) while UnknownWriteCommand2(XX=0x0001) != 0x00: pass
The odd thing is, that the memory of the GT-800 does *NOT* contain 0xFF after an erase. Erased blocks seem to contain ‘random’ data. On closer inspection it is not random. Erased blocks start with one of following four sequences:
0xa62d0f21 affb0f12 0x8dad34a1 962d0ee0 0xbc7b97b3 facc3c12 0xbd3b69d3 df8b23e0
Even @trip does not seem to be aware of this. Aparently it reads the blocks from high to low and expects an erased block to contain 0xff. Since the erased blocks don’t contain 0xff, @trip erases every block on each erase (which is taking a long time). U-gotMe also checks on the sequences above, resulting in faster erase (if the flash is not full).
The start of 0x001000 contains ‘random’ data, the remainder contains 0xff.
The UnknownPurgeCommand1 and UnknownPurgeCommand2 (which appear to be missing for the GT-800) result in 0x93 0xFF 0xFF response, indicating they really are not needed by the GT-800.
Flash layout
Memory map
The first data block of 0x1000 bytes contains configuration data, all other data blocks contain the gps trackpoints.
GT-800, GT-800Pro, GT-820Pro, GT-900Pro:
Memory map of the GT-800, GT-800Pro, GT-820Pro, GT-900Pro
Following sections are visible:
- Configuration
- Configuration data
- Track, waypoint & device log
- The area consists of 0x20 bytes log entries. Log entries represent trackpoints, waypoints or debug log statements.
- Waypoints
- Waypoints that are logged during a trip are stored here in 0x18
bytes. - Upload waypoints
- Uploaded routes are stored here as a series of waypoints. Waypoints are stored in 0x120 bytes each.
- ???
- To be determined
Waypoints that are logged with a press on the button during a trip are stored as part of the track in Track, Waypoint & Device log. They are also stored in the Waypoints section. If the tracks are erased, they remain in here.
Space for trackpoints: (0x700000 – 0x1000) / 0x20 = 229248
Space for waypoints: (0x707000-0x700000) / 0x18 = 1194
Space for uploadable waypoints: (0x70f000 – 0x707000) / 0x120 = 113
Note: the GT-820 and GT-900 (non-pro) have a smaller flash (2 MByte iso. 8 MByte). They must have another memory map. I guess just the track log is smaller, leaving space for ‘just’ 32640 track points.
Configuration data
On the GT-100, GT-200:
Offset | Type | Description |
0x0000: | uint8 | number of schedule table plans (1 if no schedule used) |
0x0001: | uint16 | first schedule day (days since 01.01.2000 + 1) |
0x0003: | uint8 | flags0x01: debug mode (save extra records for debugging, fw 2.15)0x02: recycle record if memory full (fw 2.15)0x04: schedule enabled0x08: GT200e dual mode0x10: obsolete
0x20: schedule is repeat? 0x40: button disabled (gated by password command?) 0x80: LED flashing when valid data is recorded is disabled |
0x0004: | uint8 | max allowed time when button is pushed and start tracer mode? |
0x0005: | uint8 | initial timeout when button is pushed and start tracer mode? |
0x0004: | uint8 | max allowed time when RTC power of GPS is lost (data/time is not a valid value) |
0x0005: | uint8 | initial timeout when RTC power of GPS is lost (data/time is not a valid value) |
0x0008: | uint8 | schedule date offset: start date = utc date + offset |
0x0009..0x00ff: | uint4 | schedule table plans (1 if no schedule used, one-based), if terminated with 0 recording is stopped, 0xff means loop from beginning0x0100: schedule table entries for plan 1 (normally Sunday, no schedule)0x0200: schedule table entries for plan 2 (normally Monday)0x0300: schedule table entries for plan 3 (normally Tuesday)0x0400: schedule table entries for plan 4 (normally Wednesday)0x0500: schedule table entries for plan 5 (normally Thursday)
0x0600: schedule table entries for plan 6 (normally Friday) 0x0700: schedule table entries for plan 7 (normally Saturday) |
0x0800: | uint8 | security version; 0x00 |
0x0801: | uint8 | password enabled: 0x80 |
0x0802: | uint8 | password length in bytes (maximum 0x80) |
0x0803..0x0882: | utf16le | password |
On the GT-800(Pro): To be determined
Offset | Type | Description |
0x0000: | uint16 | ? |
0x0002: | uint16 | ? |
0x0004: | uint16 | Log interval in seconds (little endian) |
0x0013: | uint8 | Screen rotation 0x00 – normal, 0x10 – rotated, |
On the GT-820 and GT-900:
Offset | Type | Description |
0x0000: | uint16 | ? |
0x0002: | uint16 | ? |
0x0004: | uint16 | Log interval in seconds (little endian) |
0x0012: | uint8 | Bit fields:- 0x40: ?- 0x10: Powersaving 0 = off, 1 = on, |
0x0013: | uint8 | Bit fields:- 0x80: 12/24 hour clock – 0 = 24 hr, 1 = 12 hr- 0x40: sound – 0 = on, 1 = off (!)- 0x10: Screen rotation 0 = normal, 1 = rotated, |
0x0070: | uint16 | Time difference with respect to UTC in minutes (little endian) |
0x0072: | uint16 | Auto pause speed in 0.1 km/h (0xffff = off, 10-990) |
0x0074: | uint8 | Pedometer sensitity (0 = high, 1 = normal, 2 = low |
0x0075: | uint8 | Units (0x00 – Metric, 0x01 – Imperial), |
0x0076: | uint8 | Language (0x00 – English, 0x06 – Dutch), |
0x0080: | uint32 | Altitude calibration (offset of reading with respect to measured barometic value in cm) |
0x00B0: | uint16 | User profile – Lenght in mm (little endian) |
0x00B2: | uint16 | User profile – Weight in 10g (div 100 for kg, little endian) |
0x00B4: | uint8 | User profile – Age in years |
0x00B5: | uint8 | User profile – Gender 0x00: female, 0x01: male |
0x00C6: | uint16 | Alert – Duration 1-999 min or 0 for off |
0x00CC: | uint8 | Alert – Heartrate upper zone (1-5 or 0 for off) |
0x00CD: | uint8 | Alert – Heartrate lower zone (1-upper or 0 for off) |
0x00D4: | uint32 | Alert – Distance in meter (100-999000), or 0 for off, little endian |
Schedule (GT-100, GT-200)
Schedule table entries are stored in records of 0x40 bytes:
Offset | Type | Description |
0x00: | uint8 | start hour (0xff if invalid, 0x00 if no schedule) |
0x01: | uint8 | start minute (0xff if invalid, 0x00 if no schedule) |
0x02: | uint8 | end hour (0xff if invalid, 0x00 if no schedule) |
0x03: | uint8 | end minute (0xff if invalid, 0x00 if no schedule) |
… | ||
0x07: | uint8 | logging interval (number of seconds – 1) |
0x08: | uint16b | logging interval change speed * 1e2 (in m/s) |
0x0a: | uint8 | changed logging interval (number of seconds – 1) |
… |
Trackpoints/waypoints data (GT-100, GT-200)
Trackpoints are stored in records of 0x20 bytes:
Offset | Type | Description |
0x00: | uint8 | flags: 0x01: RTC calibration log (only in debug mode) 0x02: time out log 0x04: normal log (0) or waypoint log (1) (type = -1) 0x08: timeout > ok criteria? 0x10: navigation data invalid 0x20: track stop (type = -4) 0x40: track start (type = -2) 0x80: debug mode (64 byte trackpoints) |
0x01: | uint8 | YYYYMMMMYY year – 2000 (modulo 16)MM month (starting with 1) |
0x02: | uint16b | DDDDDHHHHHMMMMMMDD day of month (starting with 1)HH hourMM minute |
0x04: | uint16b | seconds * 1000 + milliseconds |
0x06: | uint16b | AAAAEEEEEEEEEEEEAA unknown, found values 0 (common) and 1 (for flags = 0x12)EE EHPE * 1e2 / 16 (in m) |
0x08: | uint32b | satellite map (one bit per satellite) |
0x0c: | int32b | latitude * 1e7 (in degrees) |
0x10: | int32b | longitude * 1e7 (in degrees) |
0x14: | int32b | elevation * 1e2 (in m) |
0x18: | uint16b | speed * 1e2 (in m/s) |
0x1a: | uint16b | course * 1e2 (in degrees) |
0x1c: | uint8 | timeout in s |
0x1d: | uint8 | SSSSCCCCSS maximum found SV for this recordCC qualified satellite number with C/N value > criteria |
0x1e: | uint8 | weight criteria |
0x1f: | uint8 | qualified satellite number with C/N value > criteria? or sleep time (unit 16s, debug mode) |
Trackpoints/waypoints data (GT-800)
NOTE: For the GT-800 the map appears somewhat different. Next is what I confirmed by comparisson and what is used in the U-gotMe software:
Offset | Type | Description |
0x00: | uint8 | flags: 0x04: record is a waypoint 0x10: navigation data invalid 0x20: track stop (type = -4) 0x40: track start (type = -2)Specials: 0xF1: The record is a device log record |
0x01: | uint8 | YYYYMMMMYY year – 2000 (modulo 16)MM month (starting with 1) |
0x02: | uint16b | DDDDDHHHHHMMMMMMDD day of month (starting with 1)HH hourMM minute |
0x04: | uint16b | seconds * 1000 + milliseconds |
0x06: | uint16b | AAAAEEEEEEEEEEEEAA unknown, found values 0 (common) and 1 (for flags = 0x12)EE EHPE * 1e2 / 16 (in m) |
0x08: | int32b | elevation measured by pressure * 1e2 (in m) (Pro version only) |
0x0c: | int32b | latitude * 1e7 (in degrees) |
0x10: | int32b | longitude * 1e7 (in degrees) |
0x14: | elevation measured by GPS * 1e2 (in m) | |
0x18: | uint16b | speed * 1e2 (in m/s) |
0x1a: | uint16b | course * 1e2 (in degrees) |
0x1e: | uint16b | seconds * 1000 + milliseconds of previous log record |
On the GT-800 the track log is also used to store debug messages. One trackpoint space of 0x20 bytes is used to store the message.
Offset | Type | Description |
0x00: | uint8 | flags = 0xf1 |
0x01: | uint8 | YYYYMMMMYY year – 2000 (modulo 16)MM month (starting with 1) |
0x02: | uint16b | DDDDDHHHHHMMMMMM DD day of month (starting with 1)HH hourMM minute |
0x04: | uint16b | seconds * 1000 + milliseconds |
0x06: | 24 bytes | Debug message in 24 ASCII characters (remaining space: 0x00) |
0x1e: | uint16b | seconds * 1000 + milliseconds of previous log record |
Messages observed for example:
'VER:Sep 30 2011 18:22:19' 'PCB=3 R=10005F' '***HEART_BEAT***' '!!!SYSTEM OFF' 'POWER DOWN 00090000' 'POWER UP 00000001'
Even (dis)connecting the device to the USB port makes it writing log messages in this way. Messages differ between the GT-800 Pro (7.11) and the GT-800 (6.05)
Trackpoints/waypoints data (GT-820, GT-900)
Offset | Type | Description |
0x00: | uint8 | flags: 0x00: waypoint record 0x04: record is a waypoint 0xF1: The record is a device log record 0xF5: Heartbeat record 0x??: Cadence record? |
0x01: | uint8 | YYYYMMMMYY year – 2000 (modulo 16)MM month (starting with 1) |
0x02: | uint16b | DDDDDHHHHHMMMMMMDD day of month (starting with 1)HH hourMM minute |
0x04: | uint16b | seconds * 1000 + milliseconds |
0x06: | uint16b | AAAAEEEEEEEEEEEEAA unknown, found values 0 (common) and 1 (for flags = 0x12)EE EHPE * 1e2 / 16 (in m) |
0x08: | int32b | elevation measured by pressure * 1e2 (in m) (Pro version only) |
0x0c: | int32b | latitude * 1e7 (in degrees) |
0x10: | int32b | longitude * 1e7 (in degrees) |
0x14: | elevation measured by GPS * 1e2 (in m) | |
0x18: | uint16b | speed * 1e2 (in m/s) |
0x1a: | uint16b | course * 1e2 (in degrees) |
0x1e: | uint16b | seconds * 1000 + milliseconds of previous log record |
On the GT-900 the track log is also used to store debug messages. One trackpoint space of 0x20 bytes is used to store the message.
Offset | Type | Description |
0x00: | uint8 | flags = 0xf1 |
0x01: | uint8 | YYYYMMMMYY year – 2000 (modulo 16)MM month (starting with 1) |
0x02: | uint16b | DDDDDHHHHHMMMMMM DD day of month (starting with 1)HH hourMM minute |
0x04: | uint16b | seconds * 1000 + milliseconds |
0x06: | 24 bytes | Debug message in 24 ASCII characters (remaining space: 0x00) |
0x1e: | uint16b | seconds * 1000 + milliseconds of previous log record |
Messages observed for example:
'VER:Dec 3 2012 16:34:18' 'PCB=20 R=10005F' 'BOOT REG1 00000040' '***HEART_BEAT**' 'RESET COUNTER' '!!!SYSTEM OFF' 'POWER DOWN 00090000' 'POWER UP 00000001' 'Manual SCAN' 'BT_Scan BEGIN' 'BT Connect'
On the GT-900 has an additional message that logs the heartrate. This message starts with 0xF5. It occurs every 24 seconds, presenting 24 values (hence, one reading per second). I tested it with the HRM-10 hearrate sensor.
Offset | Type | Description |
0x00: | uint8 | flags = 0xF5 |
0x01: | uint8 | YYYYMMMMYY year – 2000 (modulo 16)MM month (starting with 1) |
0x02: | uint16b | DDDDDHHHHHMMMMMM DD day of month (starting with 1)HH hourMM minute |
0x04: | uint16b | seconds * 1000 + milliseconds |
0x06: | 24 bytes | Heartrate values. Each byte is a measurement in bpm. Or 0xFF if value unknown |
0x1e: | uint16b | seconds * 1000 + milliseconds of previous log record |
It is also possible to attach a bluetooth cadence/speed sensor to the GT-900. However, I did not test.
Waypoints (GT-800/800Pro, GT-820Pro, GT-900Pro)
On the GT-800 the area 0x700000 to 0x707000 contains a list of logged waypoints. Each waypoint is stored as a 0x18 byte record.
Offset | Type | Description |
0x00: | uint32 | Always 5A 48 20 02?? |
0x04: | uint32 | Latitude in 10E-7 degrees (little endian) |
0x08: | uint32 | Longitude in 10E-7 degrees (little endian) |
0x0C: | uint32 | Elevation in cm |
0x10: | uint32 | Seconds since 31-12-1999 00:00 (=epoch time +946598400). Little endian. In 2136 the device will have a problem 😉 |
0x14: | uint32 | Counter counting from 1 upwards. Little endian |
Note: waypoints are stored twice: in the track log (as a special type of track point) and in the waypoint log. Erasing tracks results in erasing the waypoints in the track log, but not in the waypoint log. The GT-800 device uses the waypoints in the waypoint log to show on the display (waypoint locator).
Uploadable route points (GT-800, GT-820Pro, GT-900Pro)
Uploadable route points are stored in records of 0x120 bytes:
Example:
B8 48 20 02 7A B7 BD 1F E4 52 ED 03 9C FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 01 00 00 20 00 00 00 00 00 00 00 00 00 00 00 80 F9 F1 E3 27 00 00 00 00 00 00 00 00 00 00 00 80 FD FB F7 2F 00 00 00 00 00 00 00 00 00 00 00 80 0D 1B 36 2C 3F 1C 02 22 02 00 00 00 00 00 00 80 0D 1B 36 2C 41 22 02 39 04 00 00 00 00 00 00 80 0D 1B 36 2C 41 41 02 21 04 00 00 00 00 00 00 80 FD FB F7 2F 41 41 82 20 08 00 00 00 00 00 00 80 F9 F3 E7 2F 3F 41 82 20 08 00 00 00 00 00 00 80 01 03 06 2C 01 41 82 20 08 00 00 00 00 00 00 80 01 03 06 2C 01 41 82 20 08 00 00 00 00 00 00 80 0D 1B 36 2C 01 22 82 20 08 00 00 00 00 00 00 80 FD FB F7 2F 01 1C 02 21 04 00 00 00 00 00 00 80 F9 F1 E3 27 00 00 00 01 04 00 00 00 00 00 00 80 01 00 00 20 00 00 00 02 02 00 00 00 00 00 00 80 01 00 00 20 00 00 00 00 00 00 00 00 00 00 00 80