All frames :
  • start with two mode bytes and two checksum bytes,
  • have a static length,
  • are arranged Little-Endian,
  • can be skipped.
Files may or may not start with an 0x0AD0 Header frame.

Some frames structure build upon previous structures so you can make a convenient union out of it all : oao_frame.h.
With GCC, you'll need to add -mno-ms-bitfields to the compile flags on some platforms : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991

In the grand scheme of things, you probably only need to interpret mode 0x0AD4 (GNSS aligned on the second).

Checksum
Fletcher's checksum of every bytes in a frame except the two checksum bytes.

/*
 * Length of the frame in bytes,
 * pointer to the frame bytes buffer.
 */
bool checksum_verify(const uint16_t length, const uint8_t* buffer) {
uint8_t checksum_a = 0, checksum_b = 0; /* Sum the two first bytes */ for(uint16_t i = 0; i < 2; i++) { checksum_b += (checksum_a += buffer[i]); } /* Skip the two checksum bytes */ /* Sum the following bytes */ for(uint16_t i = 4; i < length; i++) { checksum_b += (checksum_a += buffer[i]); } /* Compare the computed checksum to the checksum in the frame */ return checksum_a == buffer[2] && checksum_b == buffer[3]; }
Header frame
Mode is 0x0AD0, length is 512 bytes, hexadecimal example :
D0 0A CA CC 94 05 4A 75 6C 69 65 6E 00 00 00 00 6D D4 9F 32 65 01 00 00 6F 78 21 1E BE C1 50 02 C7 0A 01 00 84 BA F2 32 65 01 00 00 30 DC 20 1E D9 3D 4F 02 0E 2D 01 00 93 D7 6A 01 03 D9 20 1E 79 76 43 02 5F 83 00 00 00 00 00 00 E4 FA 2A 1E 3F 9D 52 02 F0 37 01 00 E6 65 00 00 12 42 00 00 4F 05 00 00 97 55 71 5B 48 66 00 00 EB 5B 71 5B 2A 65 00 00 B4 53 71 5B 47 63 00 00 F2 53 71 5B 32 61 00 00 CB 50 71 5B 52 5C 00 00 9B 55 71 5B E2 64 00 00 08 5C 71 5B B6 63 00 00 B6 53 71 5B F3 60 00 00 F7 53 71 5B 13 5E 00 00 4A 55 71 5B AC 59 00 00 E4 5D 71 5B A5 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B4 55 71 5B 56 63 00 00 0B 5C 71 5B 40 63 00 00 B7 53 71 5B 97 5F 00 00 F9 53 71 5B C5 5C 00 00 CD 50 71 5B D6 58 00 00 16 5C 71 5B EB 60 00 00 BE 55 71 5B 57 60 00 00 19 54 71 5B 02 5C 00 00 BA 53 71 5B ED 5A 00 00 CE 50 71 5B 10 58 00 00 44 5C 71 5B 05 5D 00 00 2A 54 71 5B 18 59 00 00 F5 5C 71 5B 69 57 00 00 4C 55 71 5B F3 54 00 00 D5 50 71 5B 58 53 00 00 C7 5C 71 5B C8 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 B3 06 81 59 51 FB F1 74 85 F2 AF 67 D8 3B 95 7B 9F D6 57 04 F9 70 C4 01 21 BA DA 3C D4 C0 05 52 D0 5F 6F D7 EC 66 63 F5 B3 60 6B 81 79 7A 44 C4 0C 57 22 2A EF 40 84 22 6B 33 79 7B 94 2D 04
Integer type Name Value (hex) Informations Interpreted as
16-bit unsigned Mode D0 0A   0x0AD0 Header
(512 bytes)
16-bit unsigned Checksum CA CC    
16-bit unsigned Identifier 94 05   1428
80-bit signed Nickname 4A 75 6C 69 65
6E 00 00 00 00
  Julien
64-bit unsigned Log start date 6D D4 9F 32 65 01 00 00 Milliseconds since Unix time 2018-08-13T09:31:00.077Z
32-bit signed Log start latitude 6F 78 21 1E Divide by 10^6 50.5509999 degrees
32-bit signed Log start longitude BE C1 50 02 Divide by 10^6 3.8846910 degrees
32-bit signed Log start altitude (MSL) C7 0A 01 00 Divide by 10^2 68.295 m
64-bit unsigned Log end date 84 BA F2 32 65 01 00 00 Milliseconds since Unix time 2018-08-13T11:01:32.932Z
32-bit signed Log end latitude 30 DC 20 1E Divide by 10^6 50.5470000 degrees
32-bit signed Log end longitude D9 3D 4F 02 Divide by 10^6 3.8747609 degrees
32-bit signed Log end altitude (MSL) 0E 2D 01 00 Divide by 10^2 77.070 m
32-bit unsigned Total distance 93 D7 6A 01 Divide by 10^2 23779.219 m
32-bit signed Minimum latitude 03 D9 20 1E Divide by 10^6 50.5469187 degrees
32-bit signed Minimum longitude 79 76 43 02 Divide by 10^6 3.7975673 degrees
32-bit signed Minimum altitude (MSL) 5F 83 00 00 Divide by 10^2 33.631
32-bit unsigned Minimum speed 00 00 00 00 Divide by 10^2 0 m/s
32-bit signed Maximum latitude E4 FA 2A 1E Divide by 10^6 50.6133220 degrees
32-bit signed Maximum longitude 3F 9D 52 02 Divide by 10^6 3.8968639 degrees
32-bit signed Maximum altitude (MSL) F0 37 01 00 Divide by 10^2 79.856 m
32-bit unsigned Maximum speed E6 65 00 00 Divide by 10^2 26.086 m/s
32-bit unsigned Speed average
above 12kn
12 42 00 00 Divide by 10^2 16.914 m/s
32-bit unsigned Seconds spent
above 12kn
4F 05 00 00 Seconds since log start 1359 s
32-bit unsigned Best over 1s #1 time 97 55 71 5B Seconds since Unix time 2018-08-13T09:55:35Z
32-bit unsigned Best over 1s #1 value 48 66 00 00 Divide by 10^2 26.184 m/s
32-bit unsigned Best over 1s #2 time EB 5B 71 5B Seconds since Unix time 2018-08-13T10:22:35Z
32-bit unsigned Best over 1s #2 value 2A 65 00 00 Divide by 10^2 25.898 m/s
32-bit unsigned Best over 1s #3 time B4 53 71 5B Seconds since Unix time 2018-08-13T09:47:32Z
32-bit unsigned Best over 1s #3 value 47 63 00 00 Divide by 10^2 25.415 m/s
32-bit unsigned Best over 1s #4 time F2 53 71 5B Seconds since Unix time 2018-08-13T09:48:34Z
32-bit unsigned Best over 1s #4 value 32 61 00 00 Divide by 10^2 24.882 m/s
32-bit unsigned Best over 1s #5 time CB 50 71 5B Seconds since Unix time 2018-08-13T09:35:07Z
32-bit unsigned Best over 1s #5 value 52 5C 00 00 Divide by 10^2 23.634 m/s
Repeat bests_over_1s for bests_over_10s, bests_over_1h, bests_over_500m, bests_over_1000m, bests_over_1852m, bests_gybe_min
32-bit unsigned Elevation gain 00 00 00 00 New, divide by 10^2 0 m
64-byte unsigned Unused 64 times 00
64-byte unsigned Signature 80 B3 06 81 59 51 FB F1 74 85 F2 AF 67 D8 3B 95 7B 9F D6 57 04 F9 70 C4 01 21 BA DA 3C D4 C0 05 52 D0 5F 6F D7 EC 66 63 F5 B3 60 6B 81 79 7A 44 C4 0C 57 22 2A EF 40 84 22 6B 33 79 7B 94 2D 04 Authenticity check for competitions
Track frame
Mode is 0x0AD1, length is 12 bytes, hexadecimal example :
D1 0A 2F 37 0E 2E 22 1E 6C 19 51 02
Integer type Name Value (hex) Informations Interpreted as
16-bit unsigned Mode D1 0A   0x0AD1 Track (12 bytes)
16-bit unsigned Checksum 2F 37    
32-bit signed Latitude 0E 2E 22 1E Divide by 10^6 50.5556494 degrees
32-bit signed Longitude 6C 19 51 02 Divide by 10^6 3.8869356 degrees
Emergency frame
Mode is 0x0AD2, length is 34 bytes, hexadecimal example :
D2 0A A3 38 0E 2E 22 1E 6C 19 51 02 F7 EA 00 00 A4 45 00 00 55 77 6F 01 C0 28 D3 32 65 01 00 00 03 17
Integer type Name Value (hex) Informations Interpreted as
16-bit unsigned Mode D2 0A   0x0AD2 Emergency (34 bytes)
16-bit unsigned Checksum A3 38    
32-bit signed Latitude 0E 2E 22 1E Divide by 10^6 50.5556494 degrees
32-bit signed Longitude 6C 19 51 02 Divide by 10^6 3.8869356 degrees
32-bit signed Altitude MSL F7 EA 00 00 Divide by 10^2 60.151 m
32-bit unsigned Speed A4 45 00 00 Divide by 10^2 17.828 m/s
32-bit unsigned Course 55 77 6F 01 Divide by 10^4 240.823 degrees
64-bit unsigned UTC time C0 28 D3 32 65 01 00 00 Milliseconds since Unix time 2018-08-13T10:27:04.000Z
16-bit unsigned Identifier 03 17 1312
Point of interest frame
Mode is 0x0AD3, length is 34 bytes, hexadecimal example :
D3 0A A4 58 0E 2E 22 1E 6C 19 51 02 F7 EA 00 00 A4 45 00 00 55 77 6F 01 C0 28 D3 32 65 01 00 00 03 17
Integer type Name Value (hex) Informations Interpreted as
16-bit unsigned Mode D3 0A   0x0AD3 POI (34 bytes)
16-bit unsigned Checksum A4 58    
32-bit signed Latitude 0E 2E 22 1E Divide by 10^6 50.5556494 degrees
32-bit signed Longitude 6C 19 51 02 Divide by 10^6 3.8869356 degrees
32-bit signed Altitude MSL F7 EA 00 00 Divide by 10^2 60.151 m
32-bit unsigned Speed A4 45 00 00 Divide by 10^2 17.828 m/s
32-bit unsigned Course 55 77 6F 01 Divide by 10^4 240.823 degrees
64-bit unsigned UTC time C0 28 D3 32 65 01 00 00 Milliseconds since Unix time 2018-08-13T10:27:04.000Z
8-bit unsigned Fix type 03 0 : none, 2 : 2D, 3 : 3D 3D
8-bit unsigned Satellites 17 Used in this solution 23
GNSS frame
Mode is 0x0AD4 or 0x0AD5, length is 52 bytes, hexadecimal example :
D4 0A E3 EE 0E 2E 22 1E 6C 19 51 02 F7 EA 00 00 A4 45 00 00 55 77 6F 01 C0 28 D3 32 65 01 00 00 03 17 56 00 00 00 6D 02 00 00 02 03 00 00 70 A3 00 00 61 00
0x0AD4 are frames aligned on the second (4.000s, 5.000s, 6.000s, ...),
0x0AD5 are frames unaligned on the second (4.800s, 4.900s, 5.100s, ...).
Aside from the mode, both frames are identical. This allows you to skip unaligned frames quickly.
Integer type Name Value (hex) Informations Interpreted as
16-bit unsigned Mode D4 0A   0x0AD4 GNSS aligned
(52 bytes)
16-bit unsigned Checksum E3 EE    
32-bit signed Latitude 0E 2E 22 1E Divide by 10^6 50.5556494 degrees
32-bit signed Longitude 6C 19 51 02 Divide by 10^6 3.8869356 degrees
32-bit signed Altitude MSL F7 EA 00 00 Divide by 10^2 60.151 m
32-bit unsigned Speed A4 45 00 00 Divide by 10^2 17.828 m/s
32-bit unsigned Course 55 77 6F 01 Divide by 10^4 240.823 degrees
64-bit unsigned UTC time C0 28 D3 32 65 01 00 00 Milliseconds since Unix time 2018-08-13T10:27:04.000Z
8-bit unsigned Fix 03 0 : none, 2 : 2D, 3 : 3D 3D
8-bit unsigned Satellites 17 Used in this solution 23
32-bit unsigned Speed accuracy 56 00 00 00 Divide by 10^2 0.086 m/s
32-bit unsigned Horizontal accuracy 6D 02 00 00 Divide by 10^2 0.621 m
32-bit unsigned Vertical accuracy 02 03 00 00 Divide by 10^2 0.770 m
32-bit unsigned Heading accuracy 70 A3 00 00 Divide by 10^4 0.418 degrees
16-bit unsigned Position DOP 61 00 Divide by 10^2 0.97
Inertial Measurement Unit frame
Mode is 0x0AD6, length is 32 bytes, hexadecimal example :
D6 0A 99 D3 8E BB 52 33 65 01 00 00 51 3B 68 00 60 03 36 E8 FF FF 10 00 02 00 FE FF 01 00 02 00
Integer type Name Value (hex) Informations Interpreted as
16-bit unsigned Mode D6 0A   0x0AD6 IMU (32 bytes)
16-bit unsigned Checksum 99 D3    
64-bit unsigned UTC time 8E BB 52 33 65 01 00 00 Milliseconds since Unix time 2018-08-13T12:46:24.654Z
16-bit signed Attitude W 51 3B * (1 / (1 << 14)) 0.927
16-bit signed Attitude X 68 00 * (1 / (1 << 14)) 0.006
16-bit signed Attitude Y 60 03 * (1 / (1 << 14)) 0.053
16-bit signed Attitude Z 36 E8 * (1 / (1 << 14)) -0.372
16-bit signed Angular velocity X FF FF * (1 / (1 << 9)) -0.002 rad/s
16-bit signed Angular velocity Y 10 00 * (1 / (1 << 9)) 0.031 rad/s
16-bit signed Angular velocity Z 02 00 * (1 / (1 << 9)) 0.004 rad/s
16-bit signed Linear acceleration X FE FF * (1 / (1 << 8)) -0.008 m/s/s
16-bit signed Linear acceleration Y 01 00 * (1 / (1 << 8)) 0.004 m/s/s
16-bit signed Linear acceleration Z 02 00 * (1 / (1 << 8)) 0.008 m/s/s