Author: Antonio Tabernero (ant@fi.upm.es)

Last modified: 9/14/2000 (with Etrex info)





 Following the thread about obtaining raw data from a Garmin GPS12

via async messages, I have prepare a brief report concerning those 

messages more related to raw data. 



 Send comments, errors, suggestions to ant@fi.upm.es



  Antonio.





History

-----------------------------------------------------------------

The original starting point was the compilation by William Soley 

of the undocumented commands of the Garmin units. Then there was 

a post indicating that a commercial product (gringo) was available 

for postprocessing pseudorange and phase info acquired from a GPS12 

(or XL), followed by the post from Jose Maria Munoz describing most 

of the interesting async events.



The main expansion of this document over Jose Maria's post concerns 

messages 0x16, 0x37, 0x39 and a couple fields in 0x38.

 

I also would like to thank Sam Storm van Leeuwen, whose comments 

and explanations on the peculiarities of the GPS12 receiver made 

me waste a bit more time on my GPS12. He also found a more general

way of obtaining the fractional phase.



D.J. Johnson was kind enough to provide me with a binary log of an

Garmin Etrex from which I was able to (more or less) find out where 

the raw data is output in those units.





Programs

------------------------------------------------------------------

As I understand that the info presented is necessarily of a 

local (both in time and space) nature and that the best way to

learn more is to get more people involved, I have prepared the 

programs that I have been using so that they can be useful to 

other people.



Have a look at the following address to download or learn more 

about these programs:



   http://artico.lma.fi.upm.es/numerico/miembros/antonio/async



The following report also lives there.







                           REPORT

----------------------------------------------------------------

----------------------------------------------------------------

INDEX:



1. ASYNC EVENTS IN THE GARMIN GPS12 AND RAW DATA INFORMATION:

     

   1.1 Message 0x1a

   1.2 Message 0x33

   1.3 Message 0x38

   1.4 Message 0x39

   1.5 Message 0x16

   1.6 Message 0x37



2. TYPICAL POWER-ON PROCEDURE.





3. GENERATION OF RINEX2 FILES FROM YOUR GPS12.





4. RAW DATA IN THE GARMIN ETREX 

--------------------------------------------------------------------





1. ASYNC EVENTS IN THE GARMIN GPS12 AND RAW DATA INFORMATION





 I describe records 0x1a, 0x33, 0x38, 0x39, 0x16, and 0x37 (in that 

order).  I have named the different fields of each record (at least 

those that I think we know what they are) so that they can be 

referred in different parts of the document.





-----------------------------------------------------------------

1.1 Message ID: 0x1a (12 x 8 bytes)

-----------------------------------------------------------------



General description:

12 messages (one for each channel) indicating the SV that the channel

is tracking, its elevation, signal strenght, etc. Each message 

is composed of the following fields:



Name         svid 

Position     byte 1

Type         BYTE

Description  SVID (PRN-1). If ff, no sat is being tracked in that channel.

 

Name         elev

Position     byte 2

Type         BYTE 

Description  Elevation in degrees.



Name         Fractional Phase

Position     bytes 3-4

Type         unsigned int

Description  Only 11 bits are used. Divided by 2048 it will give us 

             the fractional carrier phase corresponding to the 

             time of the previous bunch of 0x38 records.

             BEWARE: there are reports that these field is version

                     dependent. The above interpretation is valid

                     for GPS12 ver 4.0 and XL ver 4.55, but it is not

                     for the XL ver 3.62



Name         signal_Q

Position     bytes 5-6

Type         unsigned int

Description  Signal strenght. Identical to the corresponding field of 

             the preceding 0x38 record.



Name         tracking_status

Position     bytes 7-8

Type         BYTE[2]

Description  Two bytes that seems to describe the tracking status 

             of the satellite. The first one can vary betweem 1 and 4.

             The second one seems to be a flag (0-1).  The most 

             important value seems to be the first one. 

             Observed values:



             **  Correct tracking status: (4,1) or (4,0) 

             The sat is properly tracked, and the tracked_byte of 

             the 0x38 record is non zero. It seems that (4,1) is a 

             previous step to 4,0 (normal situation).

 

             ** Abnormal tracking status: (2,0) (3,0) (4,0)

             In this cases, the tracked_byte of the corresponding 

             0x38 records is zero, and a new record 0x37 is sent 

             just after each 0x38.

 

             (2,0) Initial status at power-on of the sats with 

             low signal. It seems that the GPS don't pay attention

             to them at that point. Few 0x38 are sent and those 

             show an null tracked_byte.



             (1,0) Similar results to (2,0) (tracked_byte=0 in 0x38),

             but it is not an initial situation. It looks as though 

             that sat has been declared unusable.

             

             (3,0) Special status in which a sat can fall after

             being tracked for a while. 

              



--------------------------------------------------------------------

1.2 Message ID: 0x33 (64 bytes)

--------------------------------------------------------------------

Corresponds to Garmin documented D800_Pvt_Data_Type. So no guess here,

but not useful for postprocessing either. It is interesting to 

monitor, though, to check when the GPS is able to get a fix and 

what kind of a fix.



4 bytes float   altitude above WGS84 ellipsoid

4 bytes float   Position error

4 bytes float   Horizontal pos. error

4 bytes float   Vertical pos. error

2 bytes int     Type of fix

8 bytes double  time of week (sec)

8 bytes double  latitude

8 bytes double  longitude (radians)

4 bytes float   velocity east

4 bytes float   vel north

4 bytes float   vel up

2 bytes int     leap seconds

4 bytes long    week number days







------------------------------------------------------------------

1.3 Message ID: 0x38 (37 byte long)

-------------------------------------------------------------------

Data related to a particular sat (indicated in the last byte). 

It is in this record where the most interesting info seems to be sent.





Name         phase_counter   

Position     bytes 1-4

Type         unsigned long 

Description  A counter that gets increased by about 60-70 millions

             per seconnd. The lower 11 bits give us the fractional 

             phase (it mirrors the corresponding field in the 0x1a

             record), while the upper bits (12-32) represent the integer 

             number of cycles. Just after starting the unit those 

             bits will be equal to the Integrated_phase field (see 

             below), but after a while the won't, because the phase_counter

             will roll over. The best way to compute the carrier phase 

             is thus: 

                     

                carrier_phase = integrated_phase (whole cycles) +

                                (phase_counter AND 2047)/2048.



             that is, the integrated_phase field keeps track of the 

             integer number of cycles, so we don't have to worry

             about the rollover of phase_counter. From phase_counter

             we use only its lower 11 bits to get the fractional phase.



Name         track_byte

Position     byte 5

Type         Byte  

Description  0x00 indicates some sort or problem with the sat. 

             This is the case for sats with low elevation and weak 

             signal. In that case, the other data may be unreliable. 



Name         unknown   

Position     bytes 6-8

Type         byte[3]

Description  Seem to be grouped into an integer (bytes 6-7) and a 

             flag byte (byte 8) that is always? 00 or ff.

             The integer?? moves while the tracked_byte is 00 

             (the sat is not properly tracked). 

             When the sat is locked, the number gets frozen.



Name         delta_f

Position     bytes  9-10 

Type         unsigned int (interpreted as signed by substracting 32768)

Description  If we consider this field a signed integer (not as usually 

             interpreted by the machine, but considering 32768 as the 

             zero so that the value we use is actually delta_f-32768),

             it is positive for those sats with larger increments of 

             pseudoranges (going away from us) and negative for those 

             with smaller increments of pseudoranges (approaching us):



             Sat Id    delta_pseudorange   delta_f-32768

             -------------------------------------------

               10           6329               1323

               02           5638              -2402

               05           6534               2428

               15           5863              -1186

               

             The relation between those two quantities is linear and the 

             constant relating them (in a least squares fit) is very 

             close to the L1 wavelenght. That would mean that this 

             field could be a measurement/estimation? of the Doppler 

             shift (in Hertz) for each sat.



             For the above data an aproximate fit is:



               delta_f = (delta_pr - 6080) / lambda



             delta_pr is obviouly a measure of the relative speed of the

             satellite, and the origin 6080 m/s would be the false speed 

             caused by the clock drift. Once that bias is removed, the 

             relation would be:

             

               delta_f = relative_speed / lambda 

                       = L1 * (relative_speed/c)  = Doppler shift (Hz)



Name         Integrated Phase

Position     Bytes 11-14

Type         unsigned long

Description  integrated phase (whole cycles). The ratio of its increment 

             with the increment of the pseudorange field corresponds 

             with the inverse of the L1 wavelenght. Once locked, 

             the difference between both fields rarely exceed 100 cm. 



          

Name         pseudorange

Position     Bytes 15-22

Type         double

Description  Pseudorange in meters. Due to the particular idiosincrasy 

             of the GPS12, these numbers can get real large, because 

             the GPS12 allows the clock error to accumulate in them, 

             at a rate (in my unit) of about 6000 m/s.



Name         c_511500

Position     Bytes 23-26

Type         Unsigned long

Description  511500 Hz timer. 511500 ticks corresponds to a receiver's 

             second.  At the start it is incremented by exactly 511500 

             units, but once enough sats have been acquired, it can 

             vary one or two units (probably as the GPS tries to sync 

             its measurements to an exact GPS system time second.     



Name         signal_Q

Position     Bytes 27-28 

Type         Unsigned int.

Description  Measure of the signal strength or quality for that 

             satellite.  It has the same value as in the corresponding 

             field of the next 0x1a record.



Name         tow  

Position     Bytes 29-36 

Type         Double

Description  Time of week in seconds. At the start it is incremented 

             exactly by one second (511500 units of c_511500). 

             However, after enough sats have been acquired, the GPS 

             gets an idea of its internal clock drift, and (in my unit)

             511500 units of c_511500 correspond to about 1.00002 sec 

             of the receiver time. These 20 microseconds per second

             correspond to aprox. 6000 m/sec, the drift of the internal

             clock reflected in the pseudoranges. Monitoring this field

             we can check our clock drift. Also, as I have already said,

             the increments of c_511500 are not exactly 511500, as the 

             GPS tries to take each measurement synced to a GPS second.   



Name         svid

Position     Byte 37  

Type         Byte

Description  Space Vehicle ID (PRN-1) 

   



------------------------------------------------------------------

1.3 Message ID: 0x39 (35 byte long)

-------------------------------------------------------------------



BYTES 1-2  : changing.

BYTES 3-10 : fixed for each start.

BYTES 11-19: changing.

BYTES 20-34: fixed for each start. 

BYTE  35   : SVID (PRN-1)



General description:

This record is sent once per satellite when the GPS first locks to 

that satellite (svid field) and it's able to compute a valid

pseudorange. I don't know if it is sent again if the sat is 

lost and later re-acquired.



Tipycally, you will see a 0x38 record with an invalid pseudorange

field, then a record 0x39, and the the same 0x38 record with all

its counters unmodified except for the pseudorange field, that nows 

is something around 22,000,000 mts.



More on the relation of this event with others is explained later,

in the section about the start procedure.





--------------------------------------------------------------

1.4 Message ID: 0x36

---------------------------------------------------------------



General description: 

timing info + something else. These records are only sent once we 

have computed a valid pseudorange for a satellite (see power-on 

description below), and disappear if there is troubles (when

tracked_byte of record 0x38 becomes 0).



Name         c_50     

Position     Bytes 1-4

Type         unsigned long

Description  50 Hz counter, STARTING from the beginning of the week, 

             that is, c_50/50 corresponds to TOW. It gets incremented 

             in 30 count intervals, so that the resolution is 0.6 sec.

             

Name         unknown

Position     bytes 5-8 

Type         BYTE[4]

Description  seem to vary randomly.



Name         svid

Position     byte 9

Type         BYTE

Description  SVID (PRN-1)





-----------------------------------------------------------------

1.5 Message ID: 0x16

-----------------------------------------------------------------



General description:  

several hints indicate that this record could be related to 

velocity??/Doppler???  information:



* The delta_pseudorange_rate field is very similar to the difference 

  in pseudoranges divided by the time increment.



* Also, using the phase field of the 0x38 record as a reference,

  and studying the behaviour of this field compared to the 

  rate of increase of that phase we found the following:

 

                   Sat Id   Signal_Q   Mean(cm)   std (cm)

                     10      12000      2.0         19 

                     02       8500     -1.3         16

                     05       6000      0.3         18

                     15      12500      0.8         17

                     18       6500     -0.2         18



  We find that this delta_pseudorange rate follows the phase rate 

  a bit more closely than the differences

  of pseudoranges shown in the other table. The improvement is 

  more clearly seen in those sats with a lower signal. 

  That would be consistent with its being a more precise 

  measurement (integrated Doppler??) of the same quantity. Again, 

  beware that this has been obtained by examining a couple 

  minutes of data, and this interpretation could be wrong.



* These 0x16 records are not sent until enough sats are acquired.



* F1 and F2 seems to be some sort of correction (Kalman filter 

  parameters/variances??) that is used when aditional info is 

  gathered.  Some observations:



  - F1 has similar values (usually 0 point something) for each group 

    of messages that are sent together for the different sats.

  - F2 can be real big (in the order of thousands) in a cold start for 

    a different position for the FIRST satellites. After a while, 

    F2 drops to its normal values of about 5.

  - In a warm start (same position,a bit later) F2 values are very 

    low from the beginning.

  - In its stable state, F2 used to be larger (about 20-30 as opposed 

    to 3-5) with SA on.



 

Name         delta_pseudorange_rate (m/s)

Position     bytes 1-4

Type         float

Description  A float that closely (usually within a meter) resembles

             the increment of the pseudorange for that sat in a second.



Name         f1

Position     bytes 5-8

Type         float

Description  Similar values for a group of messages that are sent 

             together for the different sats. 

             See general description above.



Name         pseudorange

Position     bytes 9-16

Type         double

Description  Pseudorange (ms). Same as in the preceding 0x38 record.



Name         f2

Position     bytes 17-20

Type         float 

Description  See general description above.



Name         svid

Position     byte 21

Type         BYTE

Description  SVID (PRN-1)







-----------------------------------------------------------------

1.5 Message ID: 0x37 (33 bytes)

-----------------------------------------------------------------



General description:

This message is associated to a abnormal tracking status of a 

satellite, namely, (3,0) (2,0) or (1,0) in the tracking_status 

bytes of a 0x1a record. When this situation appears, the tracked_byte 

field of the 0x38 records is put to 00, and a 0x37 record follows 

each 0x38 (at that point the 0x36 records disappear).





Name         c1

Position     bytes 1-2

Type         unsigned int

Description  (??) counter, increasing, but not exceeding a relatively

             small value (depending on the tracking status). 

             The values within a group of 0x37 messages with the 

             same time tag are strongly correlated.



Name         ??

Position     bytes 3-4

Type         BYTE[2]

Description  flags?? Mostly 00 00



Name         c2

Position     bytes 5-6

Type         unsigned int

Description  similar description as previous field c1. At power-on,

             this field is the same for all 0x37 messages with 

             the same time-tagging (for different sats), but later 

             on they differ.

 

Name         delta_f

Position     bytes 7-8

Type         unsigned int (interpreted as signed by substracting 32768)

Description  Correlated with the delta_f field of the 0x38 record. 

             In that case it would be the Doppler shift?? in Hz. 

             When 0x37 records are being sent, this field (in normal 

             conditions a slow drifter) is frozen, and is the same in 

             both (0x38 and 0x37) records. 

             When it changes, the change is first seen on this field, 

             and reflected on the next 0x38 record.

             

 

Name         countdown

Position     bytes 9-10

Type         unsigned int

Description  (??) Similar as c1 and c2 above. It also shows same

             values for each group of 0x37 records with the same

             timing at power-on. Later this sinchrony dissappears.

             

             A particular case is when the sat falls in a (3,0)

             status. In that case, the value is always? between 0 

             and 1024. If it is lower than 64, the situation remains 

             unchanged.  When it gets larger than 64, it increases 

             at a rate of 16 per second (60'' countdown). 

             When it reaches 1024 (but not before) the sat can be 

             either correctly tracked again, or a new cycle starts.



Name         pseudorange 

Position     bytes 11-18

Type         double

Description  Pseudorange looking value, but slightly different from 

             the value in the same field of the 0x38 record. My guess

             is that this value is a sort of dead-reckoning when the

             sat is not being tracked. This is based on the fact that,

             when first powered, while the 0x38 (tracked_byte=00) may 

             show an incorrect pseudorange field for the sats with a  

             tracking_status of (2,0), the pseudorange field in the 

             0x37 record has at least the ``right'' aspect (it could 

             be an educated guess based on the stored almanaq info).



Name         c511

Position     bytes 19-22

Type         unsigned long

Description  511500 Hz counter. Same value as the preceding 0x38

             record.



Name         tow

Position     bytes 23-30

Type         double

Description  time of week. Same  value as in the corresponding 

             field of the  preceding 0x38 record.



Name         ??

Position     bytes 31-32

Type         BYTE[2]

Description  flags?? Mostly 00 00, sometimes 01 or ff



Name         svid

Position     byte 33

Type         BYTE

Description  SVID (PRN-1)





-------------------------------------------------------------------- 

2. TYPICAL POWER-ON PROCEDURE:



The GPS starts sending 0x38 records for the most visible/strong 

sats.  The pseudorange fields are invalid (although its increments

are correct and coherent with the phase increments).

The increment of the c_511500 counter and tow are exactly 

511500 units and 1'' respectively.



At about 5 secs the first 0x1a (combining several sats info) is sent.



A 0x39 record is sent for a particalar sat. The pseudorange field

of the 0x38 record is replaced by a valid number:



0x38 ----------------------------------------------------------------

SVID 10: TRACK_BYTE 49 Sgn Q  9580   CC2 1684  FLAG 00

         PseudoRange     24262.1 (Counter =  593122866) Phase 289610

         TOW 201131.00703 (Counter 0.5 Mhz =  5115000)  Cont (?) 34323

0x39 ---------------------------------------------------------

SVID 10: Meaningful Pseudorange

0x38 ----------------------------------------------------------------

SVID 10: TRACK_BYTE 49 Sgn Q  9580   CC2 1684  FLAG 00

         PseudoRange  21548541.7 (Counter =  593122866) Phase 289610

         TOW 201127.21737 (Counter 0.5 Mhz =  5115000)  Cont (?) 34323  

----------------------------------------------------------------------



Inmediately after a 0x39 record is sent, we start receiving 

records 0x36 for that particular sat.

Also the tow is reset to something more close to real GPS time,

in the above example the GPS clock was almost 4'' fast (it was 

a cold start).





Only when 3 0x39 records for three different sats have been sent,

the GPS is able to get a (2D) fix, and the corresponding 0x33 records

(position/vel,etc) start coming once a second. If a fourth

satellite is locked (another 0x39 record), the fixes are 3D:



0x39 ---------------------------------------------------------

SVID 15: Meaningful Pseudorange

0x39 ---------------------------------------------------------

SVID 16: Meaningful Pseudorange

0x39 ---------------------------------------------------------

SVID 10: Meaningful Pseudorange

0x33 ----------------------------------------------------------------

Pos:  (N,E,H )  (0.7048 -0.0651 686.2358)  H_ellip=-52  FIX 1D

Wdays 3808  TOW 118123.631  Leap 13

0x33 ----------------------------------------------------------------

Pos:  (N,E,H )  (0.7048 -0.0651 686.2358)  H_ellip=-52  FIX 2D

Wdays 3808  TOW 118124.631  Leap 13

0x33 ----------------------------------------------------------------

Pos:  (N,E,H )  (0.7048 -0.0651 686.2358)  H_ellip=-52  FIX 2D

Wdays 3808  TOW 118126.000  Leap 13

0x33 ----------------------------------------------------------------

Pos:  (N,E,H )  (0.7048 -0.0651 686.2358)  H_ellip=-52  FIX 2D

Wdays 3808  TOW 118129.000  Leap 13

0x39 ---------------------------------------------------------

SVID 14: Meaningful Pseudorange

0x33 ----------------------------------------------------------------

Pos:  (N,E,H )  (0.7048 -0.0651 691.3297)  H_ellip=-52  FIX 3D

--------------------------------------------------------------------



Note the frozen height while in a 2D fix.

Also when the GPS has sent 4 0x39 records (four sats locked) the 

GPS is able to precisely estimate its clock error, and the tow is 

synced more precisely to GPS time.



From now on, the increments of tow begins to reflect the clock drift,

being in my case of about 1.00002 seconds. The increment of the 

511500 counter can change in 1 or 2 units, as the GPS tries to 

takes measurements in full GPS time seconds.



Another record that only shows when at least 3 sas are locked are the

0x16 records with ???Doppler??? info. 





---------------------------------------------------------------------

3. GENERATION OF RINEX2 FILES FROM YOUR GPS12.



Once we think we know where pseudorange and phase info is sent in the 

async messages, it is time to try to see if something useful can be 

done with it.  Writing a postprocessing software without knowing 

wheather or not we have something real to work with seems a waste of 

time.



The easiest way to check things out would be to take advantage of the

postprocessing soft available. Usually those packages work with 

something called the RINEX (Receiver INdependent Exchange) format. 

As its name implies, this RINEX format is simply a way of putting all 

the pseudorange, phase, timing info into a file, so that postprocessing

packages can work with it independently of the receiver which collected 

the data.  The advantage of the RINEX format is that the reference 

stations (CORS, EUREF, CDDIS) around the globe also publish their data 

in RINEX format. IN this way (with the proper software) our G12 generated

RINEX files could be directly postprocessed against those reference

stations.



If you want to know the state-of-the-art in this RINEX-from-GPS12

bussiness, check this 

\hlink{link}{http://artico.lma.fi.upm.es/numerico/miembros/antonio/async}





-----------------------------------------------------------------------





4. RAW DATA IN THE GARMIN ETREX.



As it was pointed out the Garmin Etrex doesnt output raw data 

information in the same format as the G12 family. However, after 

a brief examination of a binary log kindly supplied by D.J. Johnson

it seems that very similar info is present in the async messages

sent by the Etrex.



 It only happens that Garmin thought to improve on its undocumented 

messages by shuffling the fields within most messages. Here comes a 

brief description of where the interesting info is to be found in 

the Etrex. There is no description of the fields as they are common 

with the already described above.



Since the interesting info seems to be there all right it would also be 

possible to generate a Rinex file from a log of the Etrex. In order 

to do so the latest version of gar2rnx has an -etrex option.



I havent done any testing whatsoever since I dont ve access to an Etrex. 

Let me know if this is working for you.





---------------------------------------------

RECORD 0x1a (L=12 x 8 bytes)

---------------------------------------------



Same as in the G12 family. Twelve eight-byte records, one for each channel.

The fields are exactly the same though most are in different positions:



Bytes 1-2: Fractional Phase

Bytes 3-4: signal_Q

Bytes 5  : elev

Bytes 6  : svid

Bytes 7-8: tracking status



--------------------------------------------

RECORD 0x36 (L=12 bytes)

--------------------------------------------



Bytes  1-4 : c_50

Bytes  5-8 : unknown

Byte    9  : svid

Bytes 10-12: three aditional new bytes. In my (very) short piece of evidence

             they are fixed for all sats.



--------------------------------------------

RECORD 0x38 (L=40 bytes)

-------------------------------------------



Same info as in the G12 messages with three additional bytes added at the

end. The position of the old fields is as follows:



Bytes 1 - 8 : Pseudorange

Bytes 9 -16 : Tow

Bytes 17-20 : Phse_counter

Bytes 21-24 : tracked

Bytes 25-28 : Integer Integrated phase

Bytes 29-32 : c_511500

Bytes 33-34 : delta_f

Bytes 35-36 : signal_Q

Bytes 37    : svid

Bytes 38-40 : new bytes. 





--------------------------------------------

RECORD 0x16 (L=24 bytes)

--------------------------------------------



Bytes 1 - 8 : Pseudorange

Bytes 9 -12 : Delta Pseudorange

Bytes 13-16 : f1

Bytes 17-20 : f2

Bytes 21    : svid

Bytes 22-24 : new bytes











    Source: geocities.com/venu_t_t/articles

               ( geocities.com/venu_t_t)