cleanup specfile for packaging
[profile/ivi/gpsd.git] / driver_rtcm2.h
1 /*****************************************************************************
2
3 This is a decoder for RTCM-104 2.x, an obscure and complicated serial
4 protocol used for broadcasting pseudorange corrections from
5 differential-GPS reference stations.  The applicable
6 standard is
7
8 RTCM RECOMMENDED STANDARDS FOR DIFFERENTIAL NAVSTAR GPS SERVICE,
9 RTCM PAPER 194-93/SC 104-STD
10
11 Ordering instructions are accessible from <http://www.rtcm.org/>
12 under "Publications".  This describes version 2.1 of the RTCM specification.
13 RTCM-104 was later incrementally revised up to a 2.3 level before being 
14 completely redesigned as level 3.0.
15
16 Also applicable is ITU-R M.823: "Technical characteristics of
17 differential transmissions for global navigation satellite systems
18 from maritime radio beacons in the frequency band 283.5 - 315 kHz in
19 region 1 and 285 - 325 kHz in regions 2 & 3."
20
21 The RTCM 2.x protocol uses as a transport layer the GPS satellite
22 downlink protocol described in IS-GPS-200, the Navstar GPS Interface
23 Specification.  This code relies on the lower-level packet-assembly
24 code for that protocol in isgps.c.
25
26 The lower layer's job is done when it has assembled a message of up to
27 33 words of clean parity-checked data.  At this point this upper layer
28 takes over.  struct rtcm2_msg_t is overlaid on the buffer and the bitfields
29 are used to extract pieces of it.  Those pieces are copied and (where
30 necessary) reassembled into a struct rtcm2_t.
31
32 This code and the contents of isgps.c are evolved from code by Wolfgang
33 Rupprecht.  Wolfgang's decoder was loosely based on one written by
34 John Sager in 1999 (in particular the dump function emits a close
35 descendant of Sager's dump format).  Here are John Sager's original
36 notes:
37
38 The RTCM decoder prints a legible representation of the input data.
39 The RTCM SC-104 specification is copyrighted, so I cannot
40 quote it - in fact, I have never read it! Most of the information
41 used to develop the decoder came from publication ITU-R M.823.
42 This is a specification of the data transmitted from LF DGPS
43 beacons in the 300kHz band. M.823 contains most of those parts of
44 RTCM SC-104 directly relevant to the air interface (there
45 are one or two annoying and vital omissions!). Information
46 about the serial interface format was gleaned from studying
47 the output of a beacon receiver test program made available on
48 Starlink's website.
49
50 This file is Copyright (c) 2010 by the GPSD project
51 BSD terms apply: see the file COPYING in the distribution root for details.
52
53 *****************************************************************************/
54
55 #ifndef _GPSD_RTCM2_H_
56 #define _GPSD_RTCM2_H_
57
58 /*
59  * Structures for interpreting words in an RTCM-104 2.x message (after
60  * parity checking and removing inversion).  Note, these structures
61  * are overlayed on the raw data in order to decode them into
62  * bitfields; this will fail horribly if your C compiler ever
63  * introduces padding between or before bit fields, or between
64  * 8-bit-aligned bitfields and character arrays.
65  *
66  * (In practice, the only class of machines on which this is likely
67  * to fail are word-aligned architectures without barrel shifters.
68  * Very few of these are left in 2008.)
69  *
70  * The RTCM 2.1 standard is less explicit than it should be about signed-integer
71  * representations.  Two's complement is specified for prc and rrc (msg1wX),
72  * but not everywhere.
73  */
74
75 #define ZCOUNT_SCALE    0.6     /* sec */
76 #define PCSMALL         0.02    /* meters */
77 #define PCLARGE         0.32    /* meters */
78 #define RRSMALL         0.002   /* meters/sec */
79 #define RRLARGE         0.032   /* meters/sec */
80
81 #define MAXPCSMALL     (0x7FFF * PCSMALL)  /* 16-bits signed */
82 #define MAXRRSMALL     (0x7F   * RRSMALL)  /*  8-bits signed */
83
84 #define XYZ_SCALE       0.01    /* meters */
85 #define DXYZ_SCALE      0.1     /* meters */
86 #define LA_SCALE        (90.0/32767.0)  /* degrees */
87 #define LO_SCALE        (180.0/32767.0) /* degrees */
88 #define FREQ_SCALE      0.1     /* kHz */
89 #define FREQ_OFFSET     190.0   /* kHz */
90 #define CNR_OFFSET      24      /* dB */
91 #define TU_SCALE        5       /* minutes */
92
93 #pragma pack(1)
94
95 #ifndef WORDS_BIGENDIAN /* little-endian, like x86 */
96
97 struct rtcm2_msg_t {
98     struct rtcm2_msghw1 {                       /* header word 1 */
99         uint            parity:6;
100         uint            refstaid:10;    /* reference station ID */
101         uint            msgtype:6;              /* RTCM message type */
102         uint            preamble:8;             /* fixed at 01100110 */
103         uint            _pad:2;
104     } w1;
105
106     struct rtcm2_msghw2 {                       /* header word 2 */
107         uint            parity:6;
108         uint            stathlth:3;             /* station health */
109         uint            frmlen:5;
110         uint            sqnum:3;
111         uint            zcnt:13;
112         uint            _pad:2;
113     } w2;
114
115     union {
116         /* msg 1 - differential gps corrections */
117         struct rtcm2_msg1 {
118             struct b_correction_t {
119                 struct {                        /* msg 1 word 3 */
120                     uint            parity:6;
121                     int             pc1:16;
122                     uint            satident1:5;        /* satellite ID */
123                     uint            udre1:2;
124                     uint            scale1:1;
125                     uint            _pad:2;
126                 } w3;
127
128                 struct {                        /* msg 1 word 4 */
129                     uint            parity:6;
130                     uint            satident2:5;        /* satellite ID */
131                     uint            udre2:2;
132                     uint            scale2:1;
133                     uint            issuedata1:8;
134                     int             rangerate1:8;
135                     uint            _pad:2;
136                 } w4;
137
138                 struct {                        /* msg 1 word 5 */
139                     uint            parity:6;
140                     int             rangerate2:8;
141                     int             pc2:16;
142                     uint            _pad:2;
143                 } w5;
144
145                 struct {                        /* msg 1 word 6 */
146                     uint            parity:6;
147                     int             pc3_h:8;
148                     uint            satident3:5;        /* satellite ID */
149                     uint            udre3:2;
150                     uint            scale3:1;
151                     uint            issuedata2:8;
152                     uint            _pad:2;
153                 } w6;
154
155                 struct {                        /* msg 1 word 7 */
156                     uint            parity:6;
157                     uint            issuedata3:8;
158                     int             rangerate3:8;
159                     uint            pc3_l:8;            /* NOTE: uint for low byte */
160                     uint            _pad:2;
161                 } w7;
162             } corrections[(RTCM2_WORDS_MAX - 2) / 5];
163         } type1;
164
165         /* msg 3 - reference station parameters */
166         struct rtcm2_msg3 {
167             struct {
168                 uint        parity:6;
169                 uint        x_h:24;
170                 uint        _pad:2;
171             } w3;
172             struct {
173                 uint        parity:6;
174                 uint        y_h:16;
175                 uint        x_l:8;
176                 uint        _pad:2;
177             } w4;
178             struct {
179                 uint        parity:6;
180                 uint        z_h:8;
181                 uint        y_l:16;
182                 uint        _pad:2;
183             } w5;
184
185             struct {
186                 uint        parity:6;
187                 uint        z_l:24;
188                 uint        _pad:2;
189             } w6;
190         } type3;
191
192         /* msg 4 - reference station datum */
193         struct rtcm2_msg4 {
194             struct {
195                 uint        parity:6;
196                 uint        datum_alpha_char2:8;
197                 uint        datum_alpha_char1:8;
198                 uint        spare:4;
199                 uint        dat:1;
200                 uint        dgnss:3;
201                 uint        _pad:2;
202             } w3;
203             struct {
204                 uint        parity:6;
205                 uint        datum_sub_div_char2:8;
206                 uint        datum_sub_div_char1:8;
207                 uint        datum_sub_div_char3:8;
208                 uint        _pad:2;
209             } w4;
210             struct {
211                 uint        parity:6;
212                 uint        dy_h:8;
213                 uint        dx:16;
214                 uint        _pad:2;
215             } w5;
216             struct {
217                 uint        parity:6;
218                 uint        dz:24;
219                 uint        dy_l:8;
220                 uint        _pad:2;
221             } w6;
222         } type4;
223
224         /* msg 5 - constellation health */
225         struct rtcm2_msg5 {
226             struct b_health_t {
227                 uint        parity:6;
228                 uint        unassigned:2;
229                 uint        time_unhealthy:4;
230                 uint        loss_warn:1;
231                 uint        new_nav_data:1;
232                 uint        health_enable:1;
233                 uint        cn0:5;
234                 uint        data_health:3;
235                 uint        issue_of_data_link:1;
236                 uint        sat_id:5;
237                 uint        reserved:1;
238                 uint        _pad:2;
239             } health[MAXHEALTH];
240         } type5;
241
242         /* msg 6 - null message */
243
244         /* msg 7 - beacon almanac */
245         struct rtcm2_msg7 {
246             struct b_station_t {
247                 struct {
248                     uint            parity:6;
249                     int             lon_h:8;
250                     int             lat:16;
251                     uint            _pad:2;
252                 } w3;
253                 struct {
254                     uint            parity:6;
255                     uint            freq_h:6;
256                     uint            range:10;
257                     uint            lon_l:8;
258                     uint            _pad:2;
259                 } w4;
260                 struct {
261                     uint            parity:6;
262                     uint            encoding:1;
263                     uint            sync_type:1;
264                     uint            mod_mode:1;
265                     uint            bit_rate:3;
266                     /*
267                      * ITU-R M.823-2 page 9 and RTCM-SC104 v2.1 pages
268                      * 4-21 and 4-22 are in conflict over the next two
269                      * field sizes.  ITU says 9+3, RTCM says 10+2.
270                      * The latter correctly decodes the USCG station
271                      * id's so I'll use that one here. -wsr
272                      */
273                     uint            station_id:10;
274                     uint            health:2;
275                     uint            freq_l:6;
276                     uint            _pad:2;
277                 } w5;
278             } almanac[(RTCM2_WORDS_MAX - 2)/3];
279         } type7;
280
281         /* msg 16 - text msg */
282         struct rtcm2_msg16 {
283             struct {
284                 uint        parity:6;
285                 uint        byte3:8;
286                 uint        byte2:8;
287                 uint        byte1:8;
288                 uint        _pad:2;
289             } txt[RTCM2_WORDS_MAX-2];
290         } type16;
291
292         /* unknown message */
293         isgps30bits_t   rtcm2_msgunk[RTCM2_WORDS_MAX-2];
294     } msg_type;
295 };
296
297 #endif /* LITTLE_ENDIAN */
298
299 #ifdef WORDS_BIGENDIAN
300 /* This struct was generated from the above using invert-bitfields.pl */
301 #ifndef S_SPLINT_S      /* splint thinks it's a duplicate definition */
302
303 struct rtcm2_msg_t {
304     struct rtcm2_msghw1 {                       /* header word 1 */
305         uint            _pad:2;
306         uint            preamble:8;             /* fixed at 01100110 */
307         uint            msgtype:6;              /* RTCM message type */
308         uint            refstaid:10;    /* reference station ID */
309         uint            parity:6;
310     } w1;
311
312     struct rtcm2_msghw2 {                       /* header word 2 */
313         uint            _pad:2;
314         uint            zcnt:13;
315         uint            sqnum:3;
316         uint            frmlen:5;
317         uint            stathlth:3;             /* station health */
318         uint            parity:6;
319     } w2;
320
321     union {
322         /* msg 1 - differential gps corrections */
323         struct rtcm2_msg1 {
324             struct b_correction_t {
325                 struct {                        /* msg 1 word 3 */
326                     uint            _pad:2;
327                     uint            scale1:1;
328                     uint            udre1:2;
329                     uint            satident1:5;        /* satellite ID */
330                     int             pc1:16;
331                     uint            parity:6;
332                 } w3;
333
334                 struct {                        /* msg 1 word 4 */
335                     uint            _pad:2;
336                     int             rangerate1:8;
337                     uint            issuedata1:8;
338                     uint            scale2:1;
339                     uint            udre2:2;
340                     uint            satident2:5;        /* satellite ID */
341                     uint            parity:6;
342                 } w4;
343
344                 struct {                        /* msg 1 word 5 */
345                     uint            _pad:2;
346                     int             pc2:16;
347                     int             rangerate2:8;
348                     uint            parity:6;
349                 } w5;
350
351                 struct {                        /* msg 1 word 6 */
352                     uint            _pad:2;
353                     uint            issuedata2:8;
354                     uint            scale3:1;
355                     uint            udre3:2;
356                     uint            satident3:5;        /* satellite ID */
357                     int             pc3_h:8;
358                     uint            parity:6;
359                 } w6;
360
361                 struct {                        /* msg 1 word 7 */
362                     uint            _pad:2;
363                     uint            pc3_l:8;            /* NOTE: uint for low byte */
364                     int             rangerate3:8;
365                     uint            issuedata3:8;
366                     uint            parity:6;
367                 } w7;
368             } corrections[(RTCM2_WORDS_MAX - 2) / 5];
369         } type1;
370
371         /* msg 3 - reference station parameters */
372         struct rtcm2_msg3 {
373             struct {
374                 uint        _pad:2;
375                 uint        x_h:24;
376                 uint        parity:6;
377             } w3;
378             struct {
379                 uint        _pad:2;
380                 uint        x_l:8;
381                 uint        y_h:16;
382                 uint        parity:6;
383             } w4;
384             struct {
385                 uint        _pad:2;
386                 uint        y_l:16;
387                 uint        z_h:8;
388                 uint        parity:6;
389             } w5;
390
391             struct {
392                 uint        _pad:2;
393                 uint        z_l:24;
394                 uint        parity:6;
395             } w6;
396         } type3;
397
398         /* msg 4 - reference station datum */
399         struct rtcm2_msg4 {
400             struct {
401                 uint        _pad:2;
402                 uint        dgnss:3;
403                 uint        dat:1;
404                 uint        spare:4;
405                 uint        datum_alpha_char1:8;
406                 uint        datum_alpha_char2:8;
407                 uint        parity:6;
408             } w3;
409             struct {
410                 uint        _pad:2;
411                 uint        datum_sub_div_char3:8;
412                 uint        datum_sub_div_char1:8;
413                 uint        datum_sub_div_char2:8;
414                 uint        parity:6;
415             } w4;
416             struct {
417                 uint        _pad:2;
418                 uint        dx:16;
419                 uint        dy_h:8;
420                 uint        parity:6;
421             } w5;
422             struct {
423                 uint        _pad:2;
424                 uint        dy_l:8;
425                 uint        dz:24;
426                 uint        parity:6;
427             } w6;
428         } type4;
429
430         /* msg 5 - constellation health */
431         struct rtcm2_msg5 {
432             struct b_health_t {
433                 uint        _pad:2;
434                 uint        reserved:1;
435                 uint        sat_id:5;
436                 uint        issue_of_data_link:1;
437                 uint        data_health:3;
438                 uint        cn0:5;
439                 uint        health_enable:1;
440                 uint        new_nav_data:1;
441                 uint        loss_warn:1;
442                 uint        time_unhealthy:4;
443                 uint        unassigned:2;
444                 uint        parity:6;
445             } health[MAXHEALTH];
446         } type5;
447
448         /* msg 6 - null message */
449
450         /* msg 7 - beacon almanac */
451         struct rtcm2_msg7 {
452             struct b_station_t {
453                 struct {
454                     uint            _pad:2;
455                     int             lat:16;
456                     int             lon_h:8;
457                     uint            parity:6;
458                 } w3;
459                 struct {
460                     uint            _pad:2;
461                     uint            lon_l:8;
462                     uint            range:10;
463                     uint            freq_h:6;
464                     uint            parity:6;
465                 } w4;
466                 struct {
467                     uint            _pad:2;
468                     uint            freq_l:6;
469                     uint            health:2;
470                     uint            station_id:10;
471                              /* see comments in LE struct above. */
472                     uint            bit_rate:3;
473                     uint            mod_mode:1;
474                     uint            sync_type:1;
475                     uint            encoding:1;
476                     uint            parity:6;
477                 } w5;
478             } almanac[(RTCM2_WORDS_MAX - 2)/3];
479         } type7;
480
481         /* msg 16 - text msg */
482         struct rtcm2_msg16 {
483             struct {
484                 uint        _pad:2;
485                 uint        byte1:8;
486                 uint        byte2:8;
487                 uint        byte3:8;
488                 uint        parity:6;
489             } txt[RTCM2_WORDS_MAX-2];
490         } type16;
491
492         /* unknown message */
493         isgps30bits_t   rtcm2_msgunk[RTCM2_WORDS_MAX-2];
494     } msg_type;
495 };
496
497 #endif /* S_SPLINT_S */
498 #endif /* BIG ENDIAN */
499 #endif /* _GPSD_RTCM2_H_ */