OBSERVATIONS OF THE GARMIN-GARMIN PROTOCOL last update: Apr 6, 1995 author: william.soley@sun.com URL: http://playground.sun.com/pub/soley/garmin.txt (this work has nothing to do with Sun Microsystems) This is a description of the GARMIN-GARMIN protocol as spoken by the Garmin GPS-75 GPS receiver and the Garmin PCX5 MS-DOS software. The information here has been determined by observing the communication between the two units while sending "chosen plaintext". This spec is at best, incomplete, and at worst, incorrect. Lots of assumptions were made based on the observed behavior of the protocol. It is also unknown how much of this protocol is common to other Garmin products. But, unless Garmin decides to be cooperative, this is about the best we can do. Use it at your own risk! Layer 1 ------- Data is standard Async. 9600 bits per second. 8 data bits. no parity. 1 stop bit. Layer 2 ------- The data stream consists of frames each having the following format: DataLinkEscape (0x10) RecordType (one byte) $$ Length (one byte) ** $$ DataField ("length" bytes) ** $$ CheckSum (one byte) ** DataLinkEscape (0x10) EndTransmission (0x03) ** - fields indicated by "**" are subject to escape. Any occurance of a DataLinkEscape character (0x10) in these fields is preceeded by another DataLinkEscape (0x10) resulting in a pair. Escape bytes added in this way are not counted in the record length (i.e. bytes are counted before the escapes are added). $$ - the bytes comprising fields indicated by "$$" are sumed and the low-order 8 bits are then negated (2's compliment) to form the CheckSum. Any added DataLinkEscapes are not included in the sum. Layer 3 ------- When a non-ACK/NAK frame is received an ACK or NAK is sent depending on the checksum validity of the received frame. ACK/NAK frames are the same format as a regular frame: RecordType = 0x06 (ACK) or 0x15 (NAK) Length = 2 DataField = RecordType of record being acknowledged, 0x00 When a non-ACK/NAK frame is sent, the sender waits for an ACK/NAK. If a NAK is received, or if no ACK is received after about 1 second, the sender retransmits the frame. Power Up -------- When the GPS-75 is powered on, it transmits an 0x5A character. Holding the button while pressing to turn the unit on will erase the units memory and result in the messages: Stored Data Lost Searching the Sky Holding the button while pressing to turn the unit on will put the unit in TEST mode. A series of concentric rectangles will be displayed and animated to give the illusion of passing through a tunnel. Pressing will toggle between the tunnel display and a display showing: Testing ... Sgnl Amplitude 2168 TCX0 Drift -19.978 While in TEST mode, a continuous stream of RecordType=0x00, 0x01, and 0x0d messages will be sent to the serial port. Also, while in TEST mode the "<" and ">" may be used to adjust display contrast, but the adjustment does not appear to be saved. Data Presentation ----------------- short integer - length = 2 bytes, in order of increasing significance. Negative numbers are expressed as 2's compliment. Examples: 00 00 = 0x0 = 0 01 00 = 0x1 = 1 10 00 = 0x10 = 16 00 01 = 0x100 = 256 00 10 = 0x1000 = 4096 ff ff = 0xffff = -1 f0 ff = 0xfff0 = -16 long integer - length = 4 bytes, in order of increasing significance. Negative numbers are expressed as 2's compliment. Examples: 00 00 00 00 = 0x0 = 0 01 00 00 00 = 0x1 = 1 00 01 00 00 = 0x100 = 256 00 00 01 00 = 0x10000 = 65536 00 00 00 01 = 0x1000000 = 16777216 ff ff ff ff = 0xffffffff = -1 f0 ff ff ff = 0xfffffff0 = -16 float - length = 4 bytes, IEEE single precision floating point. Least signifigant byte first. This format consists of: 1 bit - sign 8 bits - exponent, excess 127 23 bits - mantissa, implied high-order 1 double - length = 8 bytes, IEEE double precision floating point. Least signifigant byte first. This format consists of: 1 bit - sign 11 bits - exponent, excess 1023 52 bits - mantissa, implied high-order 1 ASCII string - series of ASCII bytes, usually padded with blanks. Example: 47 50 53 20 37 35 20 20 32 2e 32 31 20 = "GPS 75 2.21" date/time - length = 4 bytes, long unsigned integer encoded as 86400 + number of seconds since midnight, Jan 1 1990. Note: unix_time = garmin_time + 631065600 Examples: 00 00 00 00 = 0x0 = undefined 80 51 01 00 = 0x15180 = Jan 1 1990 00:00:00 7d f0 ef 2d = 0x2deff07d = Jun 4 1994 03:09:49 long lat/lon - length = 4 bytes, long signed integer encoded as 11930464.7111111111 * lat/lon in degrees, or 683565275.576431632 * lat/lon in radians. Examples: 00 00 00 00 = 0x0 = 0.0 deg 61 0b b6 00 = 0xb60b61 = 1.0 deg 00 00 00 40 = 0x40000000 = 90.0 deg 00 00 00 c0 = 0xc0000000 = -90.0 deg 00 00 00 80 = 0x80000000 = -180.0 deg double lat/lon - length = 8 bytes, IEEE double precision floating point encoded as lat/lon in radians. Examples: 00 00 00 00 00 00 00 00 = 0.0 rad 00 00 00 00 00 00 f0 3f = 1.0 rad 00 00 00 00 00 00 f8 3f = 1.5 rad 00 00 00 00 00 00 00 40 = 2.0 rad 00 00 00 00 00 00 08 40 = 3.0 rad 00 00 00 00 00 00 f0 bf = -1.0 rad 00 00 00 00 00 00 00 c0 = -2.0 rad Record Types and Formats ------------------------ The following table describes the observed RecordTypes. ---------------------------------------------------------------- RecordType = 0x00 Length = 4 Description: Sent asynchronously while in TEST mode or when enabled by the RecordType=0x1C command, with mask 0x01. ---------------------------------------------------------------- RecordType = 0x01 SignalAmplitude Length = 4 DataField = 2 bytes - unsigned short - Signal Amplitude 2 bytes - ? 00 fe Description: Sent every 4 seconds while in TEST mode or when enabled by the RecordType=0x1C command, with mask 0x01. The exact meaning of the last 2 bytes is unknown. ---------------------------------------------------------------- RecordType = 0x06 ACK Length = 2 DataField = 1 byte - copy of RecordType from record being ACK'd 1 byte - always zero Description: The recipient is expected to retransmit the last record if an ACK is not received within about 1 second. ACK is not sent in response to ACK or NAK. ---------------------------------------------------------------- RecordType = 0x09 Unknown Length = 2 DataField = 2 bytes - ? 02 00 Description: Sent in response to 1c command. ---------------------------------------------------------------- RecordType = 0x0a Request Length = 2 DataField = 2 bytes - unsigned short - operation code 01 00 = 0x1 = download almanac (RecordType 1f) 02 00 = 0x2 = query position (RecordType 11) 03 00 = 0x3 = download proximity waypoints (RecType 13) 04 00 = 0x4 = download route (RecordType 1d and 1e) 05 00 = 0x5 = query UTC clock time (RecordType 0e) 06 00 = 0x6 = download tracks (RecordType 22) 07 00 = 0x7 = download waypoints (RecordType 23) 08 00 = 0x8 = power off 0b 00 = 0xb = set Tone=MSG+KEY then power off (beeps) Description: This record is sent to request the recipient to download the specified data records. For requests 1,3,4,6, and 7, the recipient should respond with RecordType=0x1B (Begin- Transfer), followed by some number of data records, followed by RecordType=0x0C (EndTransfer). For requests 2 and 5, the recipient should respond with a single data record. The 2nd DataField byte appears to be ignored. ---------------------------------------------------------------- RecordType = 0x0c EndTransfer Length = 2 DataField = 2 bytes - unsigned short - type of transfer being ended 01 00 = 0x1 = almanac 03 00 = 0x3 = proximity waypoints 04 00 = 0x4 = routes 06 00 = 0x6 = tracks 07 00 = 0x7 = waypoints Description: This record is sent following the last data record of an upload or download to denote the end of the transfer. ---------------------------------------------------------------- RecordType = 0x0d Event Length = 4 DataField = 2 bytes - EventType 0c 00 keyboard event (TEST mode only) 2 bytes - as follows: if EventType = 0c 00 (keyboard) then one of: 01 00 down 02 00 down + 1 sec 03 00 down + 2 sec 04 00 05 00 08 00