Decoding the GPS Navigation Message

If you are lucky, your receiver outputs navigation message data, such as almanac- and ephemeris parameters, in engineering units. Other receivers may output the navigation message in binary form as received, or in a hexadecimal presentation format (examples are given below). This pages gives a short introduction and some guidelines for the conversion to engineering units.

For clarity, please download the GPS Signal Specification (about 50 pages). This document has been used as guideline for producing this page.

Navigation message structure.

The navigation message is composed of five 'subframes'. Each subframe contains 10 words of 30 bits (see figure below).
Word 1 of each subframe is the 'telemetry word' (T), word 2 the 'handover word' (H). Within the framework of this page they contain no relevant information. Word 3 to 10 contain the relevant information.
Subframe 1 contains the GPS week number, SV acc. and health, and the clock correction parameters (C).
Subframe 2 and 3 contain the ephemeris parameters (E).
Your receiver should add for which SV number the subframes 1, 2 and 3 apply.
Subframe 4 and 5 contain 25 subcommutated pages with info on all SV's, such as almanac parameters, health, etc. Important for us is subframe 4 page 18: here (a.o.) the ionosphere correction parameters (I) are given, and the parameters relating GPS time to UTC (U).

word 
subfr 
10 
       
4 p 18     
               

The blank words in the table contain no relevant information for this page.

Conversion.

The following steps have to be made to convert from the original navigation message to parameters in engineering units:

A. Strip subframe's.
Each 30 bit word contains 24 databits and 6 parity bits. I assume, that the receiver s/w has carried out consistency checks on the data, thus I strip all telemetry words, handover words and parity bits from the data (if not already stripped by the receiver). What remains is for each subframe 8 words with 24 bits, or 8 words with 3 bytes (1 byte = 8 bits), or 24 bytes per stripped subframe.

B. Convert hex- to byte value (if your receiver outputs byte values, this step can be skipped).

C. Join multiple byte parameters into one unsigned integer (this integer must allow up to 4 bytes !) by shift-left-byte (multiply by 256) and add-byte operations.

D. Convert to 'signed'.
Some parameters are presented in the navigation message as unsigned integers, others as signed 2's complement integers. The latter require an additional conversion operation: subtract 2^n from the 'joined' value if the joined value > 2^(n-1) - 1, with n the number of bits in the joined value. For example if the joined value of an 8-bit parameter > 127, then subtract 256 from the joined value.

E. Scale to engineering unit.
Multiply the integer value by the LSB value to obtain engineering units.

In the following table all relevant parameters are listed with their place in the navigation message and the conversion operations to engineering units.

Abbr.  SF  from
word
-byte 
to
word
-byte 
join subtract multiply
by 
eff
range 
eng.
unit 
remark 
Tgd  7-3      2^8  2^-31    sec   
IODC  8-1            unity  (1) 
Toc  8-2  8-3  b1*2^8+b2    2^4  604784  sec   
af2  9-1      2^8  2^-55    sec/sec^2   
af1  9-2  9-3  b1*2^8+b2  2^16  2^-43    sec/sec   
af0  10-1  10-3  (b1*2^16+
b2*2^8+b3)
div(2^2) 
2^22  2^-31    sec  (2) 
IODE2  3-1            unity   
Crs  3-2  3-3  b1*2^8+b2  2^16  2^-5     
dn  4-1  4-2  b1*2^8+b2  2^16  2^-43    sc/sec  (3) 
M0  4-3  5-3  b1*2^24+b2*2^16
+b3*2^8+b4 
2^32  2^-31    sc  (3) 
Cuc  6-1  6-2  b1*2^8+b2  2^16  2^-29    rad   
ec  6-3  7-3  b1*2^24+b2*2^16
+b3*2^8+b4 
  2^-33  0.03  unity   
Cus  8-1  8-2  b1*2^8+b2  2^16  2^-29    rad   
rootA  8-3  9-3  b1*2^24+b2*2^16
+b3*2^8+b4 
  2^-19    m^0.5   
Toe  10-1  10-2  b1*2^8+b2    2^4  604784  sec   
Cic  3-1  3-2  b1*2^8+b2  2^16  2^-29    rad   
W0  3-3  4-3  b1*2^24+b2*2^16
+b3*2^8+b4 
2^32  2^-31    sc  (3) 
Cis  5-1  5-2  b1*2^8+b2  2^16  2^-29    rad   
i0  5-3  6-3  b1*2^24+b2*2^16
+b3*2^8+b4 
2^32  2^-31    sc  (3) 
Crc  7-1  7-2  b1*2^8+b2  2^16  2^-5     
7-3  8-3  b1*2^24+b2*2^16
+b3*2^8+b4 
2^32  2^-31    sc  (3) 
Wdot  9-1  9-3  b1*2^16+b2*2^8
+b3 
2^24  2^-43    sc/sec  (3) 
IODE3  10-1            unity   
idot  10-2  10-3  (b1*2^8+b2)
div(2^2) 
2^14  2^-43    sc/sec  (2) 
pageID  4/18  3-1    b1 mod 2^6        unity  (4), (5) 
a0  4/18  3-2      2^8  2^-30    sec   
a1  4/18  3-3      2^8  2^-27    sec/sc   
a2  4/18  4-1      2^8  2^-24    sec/sc^2   
a3  4/18  4-2      2^8  2^-24    sec/sc^3   
b0  4/18  4-3      2^8  2^11    sec   
b1  4/18  5-1      2^8  2^14    sec/sc   
b2  4/18  5-2      2^8  2^16    sec/sc^2   
b3  4/18  5-3      2^8  2^16    sec/sc^3   
leap  4/18  9-1            sec  (6) 
Abbr.  SF  from  to  join  subtract  multiply  range  eng unit  remark 

Use of the table:

Remarks:

  1. Only the eight LSB's of the IODC are processed.
  2. The 'div' operator carries out an integer division with an integer result. It is used to to strip two least significant bits from the least significant byte .
  3. Some parameters are expressed in semicircles , while your programming language expects radians or degrees. Convert by multiplying with pi or 180 deg. respectively.
  4. The 'mod' operator removes the 2 most significant bits from this byte.
  5. The page ID must have the value 56 (the ID value for subframe 4 page 18) for the following parameters to be valid.
  6. I asssume that the receiver has carried out the algorithms as specified in section 2.5.6 of the GPS Signal Specification. The user thus only requires the current number of leap seconds to convert GPS time to UTC and vice versa.

Example subframe 1 - clock parameters.

In week 926 at GPS time 586920 I downloaded the following subframe 1 string from my receiver for SV prn 30:
8B 0E 78 BF 11 26 E7 97 01 07 DF D4 15 9D 8F A0 E8 09 45 46 07 0E 90 24 00 FF EC FF 85 20.
Since this string contains 30 hex values, the Telemetry word and Handover word are still in, and can be stripped, resulting in the 24 hex values:
E7 97 01 - 07 DF D4 - 15 9D 8F - A0 E8 09 - 45 46 07 - 0E 90 24 - 00 FF EC - FF 85 20.
For clarity I added a dash between every three hex values, thus indicating the subframe words 3 to 10.
Since the info I'm interested in, is in words 7, 8, 9 and 10 only, I'll forget about word 3, 4, 5 and 6.
In the table below I list the hex values of word 7 - 10 in the first column, give the decimal value in the second column and proceed in the following columns according the algorithm of the table above.

word
byte 
hex  dec  abbrev  join  subtr  mul  unit 
7-1
7-2 
45
46 
69
70 
          
7-3  07  Tgd  3.259629E-9  sec 
8-1  0E  14  IODC  14  14  14  unity 
8-2
8-3 
90
24 
144
36 
Toc  36900  36900  590400  sec 
9-1  00  af2  sec/sec^2 
9-2
9-3 
FF
EC 
255
236 
af1  65516  -20  -2.273736E-12  sec/sec 
10-1
10-2
10-3 
FF
85
20 
255
133
32 
af0  4186440  -7864  -3.66196E-6  sec 

The last parameter contains nearly all operations - let's go step-by-step through the calculation. The joined value is: (255*256*256 + 133*256 + 32) div 4 = 16745760 div 4 = 4186440. This value is greater than 2097151 (2^21 - 1), thus 4194304 (2^22) has to be subtracted from it : 4186440 - 4194304 = -7864. Finally, this value has to be multiplied by the LSB value for this parameter, giving the value in engineering units : -7864 * 2^-31 = -7864 * 4.656612E-10 = -3.66196E-6 [sec].

Example subframe 2, 3 - ephemeris parameters.

My receiver gave me the following subframe 2 and -3 strings:
8B 0E 78 BF 11 AB OE FD 44 38 47 CB 73 82 C3 FD 72 02 8F 2F 39 0C F5 A1 0D 77 9B 90 24 7C, and:
8B 0E 78 BF 0F AE FF E1 B5 77 C3 0A 00 2F 26 BD 50 3D 1F A2 42 03 51 82 FF A3 1A 0E E8 10.

Again I stripped word 1 and 2 from both subframes, and put the remainder in the following table, which by now should be evident.

word
byte
hex dec abbr join subtr mul unit
3-1 0E 14 IODE2 14 14 14 unity
3-2
3-3
FD
44
253
68
Crs 64836 -700 -2.1875E+1 m
4-1
4-2
38
47
56
71
dn 14407 14407 1.637886E-9 sc/sec
4-3
5-1
5-2
5-3
CB
73
82
C3
203
115
130
195
M0 3413344963 -881622333 -4.105373E-1 sc
6-1
6-2
FD
72
253
114
Cuc 64882 -654 -1.218169E-6 rad
6-3
7-1
7-2
7-3
02
8F
2F
39
2
143
47
57
ec 42938169 42938169 4.99866E-3 unity
8-1
8-2
0C
F5
12
245
Cus 3317 3317 6.178394E-6 rad
8-3
9-1
9-2
9-3
A1
0D
77
9B
161
13
119
155
rootA 2702014363 2702014363 5.153683E+3 m^0.5
10-1
10-2
90
24
144
36
Toe 36900 36900 590400 sec
3-1
3-2
FF
E1
255
225
Cic 65505 -31 -5.7742E-8 rad
3-3
4-1
4-2
4-3
B5
77
C3
0A
181
119
195
10
W0 3044524810 -1250442486 -5.822826E-1 sc
5-1
5-2
00
2F
0
47
Cis 47 47 8.754432E-8 rad
5-3
6-1
6-2
6-3
26
BD
50
3D
38
189
80
61
i0 649941053 649941053 3.026523E-1 sc
7-1
7-2
1F
A2
31
162
Crc 8098 8098 2.530625E+2 m
7-3
8-1
8-2
8-3
42
03
51
82
66
3
81
130
w 1107513730 1107513730 5.157262E-1 sc
9-1
9-2
9-3
FF
A3
1A
255
163
26
Wdot 16753434 -23782 -2.7037E-9 sc/sec
10-1 0E 14 IODE3 14 14 14 unity
10-2
10-3
E8
10
232
16
idot 14852 -1532 -1.741682E-10 sc/sec

Example subframe 4 page 18 - iono and UTC parameters.

In week 926 at GPS time 588480 I downloaded the following subframe 4 page 18 string from my receiver:
8B 0E 78 BF 94 B1 78 0C 00 FF 00 2C 00 FD 00 00 00 08 00 00 00 00 24 9F 0C 90 02 0C AA AA.
I strip the first 2 words, or 6 hex values from these 30 hex values and enter the remaining 24 hex values in the table below, which shows the subsequent steps to engineering units.

word
byte 
hex
val 
dec
val 
Abbr  join  subtr  mult  unit 
3-1  78  120  pageID  56  56  56  unity 
3-2  0C  12  a0  12  12  1.117587E-8  sec 
3-3  00  a1  sec/sc 
4-1  FF  255  a2  255  -1  -5.960464E-8  sec/sc^2 
4-2  00  a3  sec/sc^3 
4-3  2C  44  b0  44  44  9.0112E+4  sec 
5-1  00  b1  sec/sc 
5-2  FD  253  b2  253  -3  -1.96608E+5  sec/sc^2 
5-3  00  b3  sec/sc^3 
6-1
6-2
6-3
7-1
7-2
7-3
8-1
8-2
8-3 
00
00
08
00
00
00
00
24
95 
           
9-1  0C  12  leap  12  12  12  sec 
9-2
9-3
10-1
10-2
10-3 
90
02
0C
AA
AA 
           

Remarks:

  1. I must have made errors and typo's. Please contact me (samsvl@nlr.nl) for giving your improvements.
  2. I have made this page for my own pleasure. I can not be held responsible for the correctness of the info in this page.
  3. Many thanks to the 'GPS Standard Positioning Service Signal Specification', 2nd edition, June 2, 1995.


This page was produced on 15 October 1997
Back to  s/w  index