U-gotMe Internals

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”.

portmon

Portmon application

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.

hercules
Hercules application

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:

gt-800_memmap

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
Offset Type Description
0x00: uint16 ?? Seems always to be B8 48 20 02
0x04: uint16 little endian: latitude * 1e7 (in degrees)
0x08: uint16 little endian: longitude * 1e7 (in degrees)
0x0c: unit16 little endian: heigth * 1e-2 (in m)
0x10-0x1F: 16 zero’s. U-gotMe uses this to store the name of the waypoint and the symbol id
0x20-0x11F: Bitmap. 16 lines of 128 bits. Each line is represented by 16 bytes (16 bytes x 8 bits=128 bits). Lsb of each byte represents the 1st pixel.lcd02The bitmap defines the upper section of the I-gotU display (in the route screen) showing the waypoint name. The waypoint number ‘999’ is overwritten by the device with the actual number