cleanup specfile for packaging
[profile/ivi/gpsd.git] / driver_rtcm3.c
1 /*****************************************************************************
2
3 This is a decoder for RTCM-104 3.x, a serial protocol used for
4 broadcasting pseudorange corrections from differential-GPS reference
5 stations.  The applicable specification is RTCM 10403.1: RTCM Paper
6 177-2006-SC104-STD.  This obsolesces the esrlier RTCM-104 2.x
7 specifications. The specification document is proprietary; ordering 
8 instructions are accessible from <http://www.rtcm.org/>
9 under "Publications".  
10
11 Unike the RTCM 2.x protocol, RTCM3.x does not use the strange
12 sliding-bit-window IS-GPS-200 protocol as a transport layer, but is a
13 self-contained byte-oriented packet protocol.  Packet recognition is
14 handled in the GPSD packet-getter state machine; this code is
15 concerned with unpacking the packets into well-behaved C structures,
16 coping with odd field lengths and fields that may overlap byte
17 boudaries.  These report structures live in gps.h.
18
19 Note that the unpacking this module does is probably useful only for
20 RTCM reporting and diagnostic tools.  It is not necessary when
21 passing RTCM corrections to a GPS, which normally should just be
22 passed an entire correction packet for processing by their internal
23 firmware.
24
25 This file is Copyright (c) 2010 by the GPSD project
26 BSD terms apply: see the file COPYING in the distribution root for details.
27
28 *****************************************************************************/
29
30 #include <sys/types.h>
31 #ifndef S_SPLINT_S
32 #include <unistd.h>
33 #endif /* S_SPLINT_S */
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <assert.h>
39 #include "gpsd_config.h"
40 #ifndef S_SPLINT_S
41 #ifdef HAVE_ARPA_INET
42 #include <arpa/inet.h>          /* for ntohl(3) and friends */
43 #endif /* HAVE_ARPA_INET */
44 #endif /* S_SPLINT_S */
45
46 #include "gpsd.h"
47 #include "bits.h"
48
49 #ifdef RTCM104V3_ENABLE
50
51 /* scaling constants for RTCM3 real number types */
52 #define PSEUDORANGE_RESOLUTION          0.2     /* DF011 */
53 #define PSEUDORANGE_DIFF_RESOLUTION     0.0005  /* DF012 */
54 #define CARRIER_NOISE_RATIO_UNITS       0.25    /* DF015 */
55 #define ANTENNA_POSITION_RESOLUTION     0.0001  /* DF025-027 */
56 #define ANTENNA_DEGREE_RESOLUTION       25e-6   /* DF062 */
57 #define GPS_EPOCH_TIME_RESOLUTION       0.1     /* DF065 */
58 #define PHASE_CORRECTION_RESOLUTION     0.5     /* DF069-070 */
59
60 /* Other magic values */
61 #define INVALID_PSEUDORANGE             0x80000 /* DF012 */
62
63 /* Large case statements make GNU indent very confused */
64 /* *INDENT-OFF* */
65 /*@ -type @*//* re-enable when we're ready to take this live */
66
67 void rtcm3_unpack( /*@out@*/ struct rtcm3_t *rtcm, char *buf)
68 /* break out the raw bits into the scaled report-structure fields */
69 {
70     unsigned int n, n2;
71     int bitcount = 0;
72     unsigned int i;
73     signed long temp;
74
75     /*@ -evalorder -sefparams -mayaliasunique @*/
76 #define ugrab(width)    (bitcount += width, ubits(buf, bitcount-width, width))
77 #define sgrab(width)    (bitcount += width, sbits(buf, bitcount-width, width))
78     assert(ugrab(8) == 0xD3);
79     assert(ugrab(6) == 0x00);
80
81     rtcm->length = (uint) ugrab(10);
82     rtcm->type = (uint) ugrab(12);
83
84     switch (rtcm->type) {
85     case 1001:                  /* GPS Basic RTK, L1 Only */
86         rtcm->rtcmtypes.rtcm3_1001.header.station_id = (uint) ugrab(12);
87         rtcm->rtcmtypes.rtcm3_1001.header.tow = (time_t) ugrab(30);
88         rtcm->rtcmtypes.rtcm3_1001.header.sync = (bool) ugrab(1);
89         rtcm->rtcmtypes.rtcm3_1001.header.satcount = (ushort) ugrab(5);
90         rtcm->rtcmtypes.rtcm3_1001.header.smoothing = (bool) ugrab(1);
91         rtcm->rtcmtypes.rtcm3_1001.header.interval = (ushort) ugrab(3);
92         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1001.header.satcount; i++) {
93             rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].ident = (ushort) ugrab(6);
94             rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.indicator =
95                 (unsigned char)ugrab(1);
96             temp = (unsigned long)ugrab(24);
97             if (temp == INVALID_PSEUDORANGE)
98                 rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.pseudorange = 0;
99             else
100                 rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.pseudorange =
101                     temp * PSEUDORANGE_RESOLUTION;
102             temp = (long)sgrab(20);
103             if (temp == INVALID_PSEUDORANGE)
104                 rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.rangediff = 0;
105             else
106                 rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.rangediff =
107                     temp * PSEUDORANGE_DIFF_RESOLUTION;
108             rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.locktime =
109                 (unsigned char)sgrab(7);
110         }
111         assert(bitcount ==
112                64 + 58 * rtcm->rtcmtypes.rtcm3_1001.header.satcount);
113         break;
114
115     case 1002:                  /* GPS Extended RTK, L1 Only */
116         rtcm->rtcmtypes.rtcm3_1002.header.station_id = (uint) ugrab(12);
117         rtcm->rtcmtypes.rtcm3_1002.header.tow = (time_t) ugrab(30);
118         rtcm->rtcmtypes.rtcm3_1002.header.sync = (bool) ugrab(1);
119         rtcm->rtcmtypes.rtcm3_1002.header.satcount = (ushort) ugrab(5);
120         rtcm->rtcmtypes.rtcm3_1002.header.smoothing = (bool) ugrab(1);
121         rtcm->rtcmtypes.rtcm3_1002.header.interval = (ushort) ugrab(3);
122         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1002.header.satcount; i++) {
123             rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].ident = (ushort) ugrab(6);
124             rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.indicator =
125                 (unsigned char)ugrab(1);
126             temp = (unsigned long)ugrab(24);
127             if (temp == INVALID_PSEUDORANGE)
128                 rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.pseudorange = 0;
129             else
130                 rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.pseudorange =
131                     temp * PSEUDORANGE_RESOLUTION;
132             temp = (long)sgrab(20);
133             if (temp == INVALID_PSEUDORANGE)
134                 rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.rangediff = 0;
135             else
136                 rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.rangediff =
137                     temp * PSEUDORANGE_DIFF_RESOLUTION;
138             rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.locktime =
139                 (unsigned char)sgrab(7);
140             rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.ambiguity =
141                 (bool) ugrab(8);
142             rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.CNR =
143                 (bool) ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
144         }
145         assert(bitcount ==
146                64 + 74 * rtcm->rtcmtypes.rtcm3_1002.header.satcount);
147         break;
148
149     case 1003:                  /* GPS Basic RTK, L1 & L2 */
150         rtcm->rtcmtypes.rtcm3_1003.header.station_id = (uint) ugrab(12);
151         rtcm->rtcmtypes.rtcm3_1003.header.tow = (time_t) ugrab(30);
152         rtcm->rtcmtypes.rtcm3_1003.header.sync = (bool) ugrab(1);
153         rtcm->rtcmtypes.rtcm3_1003.header.satcount = (ushort) ugrab(5);
154         rtcm->rtcmtypes.rtcm3_1003.header.smoothing = (bool) ugrab(1);
155         rtcm->rtcmtypes.rtcm3_1003.header.interval = (ushort) ugrab(3);
156         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1003.header.satcount; i++) {
157             rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].ident = (ushort) ugrab(6);
158             rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.indicator =
159                 (unsigned char)ugrab(1);
160             temp = (unsigned long)ugrab(24);
161             if (temp == INVALID_PSEUDORANGE)
162                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.pseudorange = 0;
163             else
164                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.pseudorange =
165                     temp * PSEUDORANGE_RESOLUTION;
166             temp = (long)sgrab(20);
167             if (temp == INVALID_PSEUDORANGE)
168                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.rangediff = 0;
169             else
170                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.rangediff =
171                     temp * PSEUDORANGE_DIFF_RESOLUTION;
172             rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.locktime =
173                 (unsigned char)sgrab(7);
174             rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.indicator =
175                 (unsigned char)ugrab(2);
176             temp = (unsigned long)ugrab(24);
177             if (temp == INVALID_PSEUDORANGE)
178                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.pseudorange = 0;
179             else
180                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.pseudorange =
181                     temp * PSEUDORANGE_RESOLUTION;
182             temp = (long)sgrab(20);
183             if (temp == INVALID_PSEUDORANGE)
184                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.rangediff = 0;
185             else
186                 rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.rangediff =
187                     temp * PSEUDORANGE_DIFF_RESOLUTION;
188             rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.locktime =
189                 (unsigned char)sgrab(7);
190         }
191         assert(bitcount ==
192                64 + 101 * rtcm->rtcmtypes.rtcm3_1003.header.satcount);
193         break;
194
195     case 1004:                  /* GPS Extended RTK, L1 & L2 */
196         rtcm->rtcmtypes.rtcm3_1004.header.station_id = (uint) ugrab(12);
197         rtcm->rtcmtypes.rtcm3_1004.header.tow = (time_t) ugrab(30);
198         rtcm->rtcmtypes.rtcm3_1004.header.sync = (bool) ugrab(1);
199         rtcm->rtcmtypes.rtcm3_1004.header.satcount = (ushort) ugrab(5);
200         rtcm->rtcmtypes.rtcm3_1004.header.smoothing = (bool) ugrab(1);
201         rtcm->rtcmtypes.rtcm3_1004.header.interval = (ushort) ugrab(3);
202         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1004.header.satcount; i++) {
203             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].ident = (ushort) ugrab(6);
204             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.indicator =
205                 (bool) ugrab(1);
206             temp = (unsigned long)ugrab(24);
207             if (temp == INVALID_PSEUDORANGE)
208                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.pseudorange = 0;
209             else
210                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.pseudorange =
211                     temp * PSEUDORANGE_RESOLUTION;
212             temp = (long)sgrab(20);
213             if (temp == INVALID_PSEUDORANGE)
214                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.rangediff = 0;
215             else
216                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.rangediff =
217                     temp * PSEUDORANGE_DIFF_RESOLUTION;
218             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.locktime =
219                 (unsigned char)sgrab(7);
220             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.ambiguity =
221                 (bool) ugrab(8);
222             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.CNR =
223                 (bool) ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
224             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.indicator =
225                 (unsigned char)ugrab(2);
226             temp = (unsigned long)ugrab(24);
227             if (temp == INVALID_PSEUDORANGE)
228                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.pseudorange = 0;
229             else
230                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.pseudorange =
231                     temp * PSEUDORANGE_RESOLUTION;
232             temp = (long)sgrab(20);
233             if (temp == INVALID_PSEUDORANGE)
234                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.rangediff = 0;
235             else
236                 rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.rangediff =
237                     temp * PSEUDORANGE_DIFF_RESOLUTION;
238             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.locktime =
239                 (unsigned char)sgrab(7);
240             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.ambiguity =
241                 (bool) ugrab(8);
242             rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.CNR =
243                 (bool) ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
244         }
245         assert(bitcount ==
246                64 + 125 * rtcm->rtcmtypes.rtcm3_1004.header.satcount);
247         break;
248
249     case 1005:                  /* Stationary Antenna Reference Point, No Height Information */
250         rtcm->rtcmtypes.rtcm3_1005.station_id = (unsigned short)ugrab(12);
251         ugrab(6);               /* reserved */
252         if ((bool) ugrab(1))
253             rtcm->rtcmtypes.rtcm3_1005.system = NAVSYSTEM_GPS;
254         else if ((bool) ugrab(1))
255             rtcm->rtcmtypes.rtcm3_1005.system = NAVSYSTEM_GLONASS;
256         else if ((bool) ugrab(1))
257             rtcm->rtcmtypes.rtcm3_1005.system = NAVSYSTEM_GALILEO;
258         rtcm->rtcmtypes.rtcm3_1005.reference_station = (bool) ugrab(1);
259         rtcm->rtcmtypes.rtcm3_1005.ecef_x =
260             sgrab(38) * ANTENNA_POSITION_RESOLUTION;
261         rtcm->rtcmtypes.rtcm3_1005.single_receiver = ugrab(1);
262         ugrab(1);
263         rtcm->rtcmtypes.rtcm3_1005.ecef_y =
264             sgrab(38) * ANTENNA_POSITION_RESOLUTION;
265         ugrab(2);
266         rtcm->rtcmtypes.rtcm3_1005.ecef_z =
267             sgrab(38) * ANTENNA_POSITION_RESOLUTION;
268         assert(bitcount == 152);
269         break;
270
271     case 1006:                  /* Stationary Antenna Reference Point, with Height Information */
272         rtcm->rtcmtypes.rtcm3_1006.station_id = (unsigned short)ugrab(12);
273         ugrab(6);               /* reserved */
274         if ((bool) ugrab(1))
275             rtcm->rtcmtypes.rtcm3_1006.system = NAVSYSTEM_GPS;
276         else if ((bool) ugrab(1))
277             rtcm->rtcmtypes.rtcm3_1006.system = NAVSYSTEM_GLONASS;
278         else if ((bool) ugrab(1))
279             rtcm->rtcmtypes.rtcm3_1006.system = NAVSYSTEM_GALILEO;
280         rtcm->rtcmtypes.rtcm3_1006.reference_station = (bool) ugrab(1);
281         rtcm->rtcmtypes.rtcm3_1006.ecef_x =
282             sgrab(38) * ANTENNA_POSITION_RESOLUTION;
283         rtcm->rtcmtypes.rtcm3_1006.single_receiver = ugrab(1);
284         ugrab(1);
285         rtcm->rtcmtypes.rtcm3_1006.ecef_y =
286             sgrab(38) * ANTENNA_POSITION_RESOLUTION;
287         ugrab(2);
288         rtcm->rtcmtypes.rtcm3_1006.ecef_z =
289             sgrab(38) * ANTENNA_POSITION_RESOLUTION;
290         rtcm->rtcmtypes.rtcm3_1006.height =
291             ugrab(16) * ANTENNA_POSITION_RESOLUTION;
292         assert(bitcount == 168);
293         break;
294
295     case 1007:                  /* Antenna Descriptor */
296         rtcm->rtcmtypes.rtcm3_1007.station_id = (unsigned short)ugrab(12);
297         n = (unsigned long)ugrab(8);
298         (void)memcpy(rtcm->rtcmtypes.rtcm3_1007.descriptor, buf + 4, n);
299         rtcm->rtcmtypes.rtcm3_1007.descriptor[n] = '\0';
300         bitcount += 8 * n;
301         rtcm->rtcmtypes.rtcm3_1007.setup_id = ugrab(8);
302         assert(bitcount == (int)(40 + 8 * n));
303         break;
304
305     case 1008:                  /* Antenna Descriptor & Serial Number */
306         rtcm->rtcmtypes.rtcm3_1008.station_id = (unsigned short)ugrab(12);
307         n = (unsigned long)ugrab(8);
308         (void)memcpy(rtcm->rtcmtypes.rtcm3_1008.descriptor, buf + 4, n);
309         rtcm->rtcmtypes.rtcm3_1008.descriptor[n] = '\0';
310         bitcount += 8 * n;
311         rtcm->rtcmtypes.rtcm3_1008.setup_id = ugrab(8);
312         n2 = (unsigned long)ugrab(8);
313         (void)memcpy(rtcm->rtcmtypes.rtcm3_1008.serial, buf + 6 + n, n2);
314         rtcm->rtcmtypes.rtcm3_1008.serial[n2] = '\0';
315         bitcount += 8 * n2;
316         assert(bitcount == (int)(48 + 8 * (n + n2)));
317         break;
318
319     case 1009:                  /* GLONASS Basic RTK, L1 Only */
320         rtcm->rtcmtypes.rtcm3_1009.header.station_id =
321             (unsigned short)ugrab(12);
322         rtcm->rtcmtypes.rtcm3_1009.header.tow = (time_t) ugrab(27);
323         rtcm->rtcmtypes.rtcm3_1009.header.sync = (bool) ugrab(1);
324         rtcm->rtcmtypes.rtcm3_1009.header.satcount = (ushort) ugrab(5);
325         rtcm->rtcmtypes.rtcm3_1009.header.smoothing = (bool) ugrab(1);
326         rtcm->rtcmtypes.rtcm3_1009.header.interval = (ushort) ugrab(3);
327         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1009.header.satcount; i++) {
328             rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].ident = (ushort) ugrab(6);
329             rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.indicator =
330                 (bool) ugrab(1);
331             rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.channel =
332                 (ushort) ugrab(5);
333             temp = (unsigned long)ugrab(25);
334             if (temp == INVALID_PSEUDORANGE)
335                 rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.pseudorange = 0;
336             else
337                 rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.pseudorange =
338                     temp * PSEUDORANGE_RESOLUTION;
339             temp = (long)sgrab(20);
340             if (temp == INVALID_PSEUDORANGE)
341                 rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.rangediff = 0;
342             else
343                 rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.rangediff =
344                     temp * PSEUDORANGE_DIFF_RESOLUTION;
345             rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.locktime =
346                 (unsigned char)sgrab(7);
347         }
348         assert(bitcount ==
349                61 + 64 * rtcm->rtcmtypes.rtcm3_1009.header.satcount);
350         break;
351
352     case 1010:                  /* GLONASS Extended RTK, L1 Only */
353         rtcm->rtcmtypes.rtcm3_1010.header.station_id =
354             (unsigned short)ugrab(12);
355         rtcm->rtcmtypes.rtcm3_1010.header.tow = (time_t) ugrab(27);
356         rtcm->rtcmtypes.rtcm3_1010.header.sync = (bool) ugrab(1);
357         rtcm->rtcmtypes.rtcm3_1010.header.satcount = (ushort) ugrab(5);
358         rtcm->rtcmtypes.rtcm3_1010.header.smoothing = (bool) ugrab(1);
359         rtcm->rtcmtypes.rtcm3_1010.header.interval = (ushort) ugrab(3);
360         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1010.header.satcount; i++) {
361             rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].ident = (ushort) ugrab(6);
362             rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.indicator =
363                 (bool) ugrab(1);
364             rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.channel =
365                 (ushort) ugrab(5);
366             temp = (unsigned long)ugrab(25);
367             if (temp == INVALID_PSEUDORANGE)
368                 rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.pseudorange = 0;
369             else
370                 rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.pseudorange =
371                     temp * PSEUDORANGE_RESOLUTION;
372             temp = (long)sgrab(20);
373             if (temp == INVALID_PSEUDORANGE)
374                 rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.rangediff = 0;
375             else
376                 rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.rangediff =
377                     temp * PSEUDORANGE_DIFF_RESOLUTION;
378             rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.locktime =
379                 (unsigned char)sgrab(7);
380             rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.ambiguity =
381                 (bool) ugrab(7);
382             rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.CNR =
383                 (bool) ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
384         }
385         assert(bitcount ==
386                61 + 79 * rtcm->rtcmtypes.rtcm3_1010.header.satcount);
387         break;
388
389     case 1011:                  /* GLONASS Basic RTK, L1 & L2 */
390         rtcm->rtcmtypes.rtcm3_1011.header.station_id =
391             (unsigned short)ugrab(12);
392         rtcm->rtcmtypes.rtcm3_1011.header.tow = (time_t) ugrab(27);
393         rtcm->rtcmtypes.rtcm3_1011.header.sync = (bool) ugrab(1);
394         rtcm->rtcmtypes.rtcm3_1011.header.satcount = (ushort) ugrab(5);
395         rtcm->rtcmtypes.rtcm3_1011.header.smoothing = (bool) ugrab(1);
396         rtcm->rtcmtypes.rtcm3_1011.header.interval = (ushort) ugrab(3);
397         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1011.header.satcount; i++) {
398             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].ident = (ushort) ugrab(6);
399             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.indicator =
400                 (bool) ugrab(1);
401             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.channel =
402                 (ushort) ugrab(5);
403             temp = (unsigned long)ugrab(25);
404             if (temp == INVALID_PSEUDORANGE)
405                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.pseudorange = 0;
406             else
407                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.pseudorange =
408                     temp * PSEUDORANGE_RESOLUTION;
409             temp = (long)sgrab(20);
410             if (temp == INVALID_PSEUDORANGE)
411                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.rangediff = 0;
412             else
413                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.rangediff =
414                     temp * PSEUDORANGE_DIFF_RESOLUTION;
415             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.locktime =
416                 (unsigned char)sgrab(7);
417             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.ambiguity =
418                 (bool) ugrab(7);
419             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.CNR =
420                 (bool) ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
421             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.indicator =
422                 (bool) ugrab(1);
423             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.channel =
424                 (ushort) ugrab(5);
425             temp = (unsigned long)ugrab(25);
426             if (temp == INVALID_PSEUDORANGE)
427                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.pseudorange = 0;
428             else
429                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.pseudorange =
430                     temp * PSEUDORANGE_RESOLUTION;
431             temp = (long)sgrab(20);
432             if (temp == INVALID_PSEUDORANGE)
433                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.rangediff = 0;
434             else
435                 rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.rangediff =
436                     temp * PSEUDORANGE_DIFF_RESOLUTION;
437             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.locktime =
438                 (unsigned char)sgrab(7);
439             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.ambiguity =
440                 (bool) ugrab(7);
441             rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.CNR =
442                 (bool) ugrab(8) * CARRIER_NOISE_RATIO_UNITS;
443         }
444         assert(bitcount ==
445                61 + 107 * rtcm->rtcmtypes.rtcm3_1011.header.satcount);
446         break;
447
448     case 1012:                  /* GLONASS Extended RTK, L1 & L2 */
449         rtcm->rtcmtypes.rtcm3_1012.header.station_id =
450             (unsigned short)ugrab(12);
451         rtcm->rtcmtypes.rtcm3_1012.header.tow = (time_t) ugrab(27);
452         rtcm->rtcmtypes.rtcm3_1012.header.sync = (bool) ugrab(1);
453         rtcm->rtcmtypes.rtcm3_1012.header.satcount = (ushort) ugrab(5);
454         rtcm->rtcmtypes.rtcm3_1012.header.smoothing = (bool) ugrab(1);
455         rtcm->rtcmtypes.rtcm3_1012.header.interval = (ushort) ugrab(3);
456         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1012.header.satcount; i++) {
457             rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].ident = (ushort) ugrab(6);
458             rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.indicator =
459                 (bool) ugrab(1);
460             rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.channel =
461                 (ushort) ugrab(5);
462             temp = (unsigned long)ugrab(25);
463             if (temp == INVALID_PSEUDORANGE)
464                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.pseudorange = 0;
465             else
466                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.pseudorange =
467                     temp * PSEUDORANGE_RESOLUTION;
468             temp = (long)sgrab(20);
469             if (temp == INVALID_PSEUDORANGE)
470                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.rangediff = 0;
471             else
472                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.rangediff =
473                     temp * PSEUDORANGE_DIFF_RESOLUTION;
474             rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.locktime =
475                 (unsigned char)sgrab(7);
476             rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.indicator =
477                 (bool) ugrab(1);
478             temp = (unsigned long)ugrab(25);
479             if (temp == INVALID_PSEUDORANGE)
480                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.pseudorange = 0;
481             else
482                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.pseudorange =
483                     temp * PSEUDORANGE_RESOLUTION;
484             temp = (long)sgrab(20);
485             if (temp == INVALID_PSEUDORANGE)
486                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.rangediff = 0;
487             else
488                 rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.rangediff =
489                     temp * PSEUDORANGE_DIFF_RESOLUTION;
490             rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.locktime =
491                 (unsigned char)sgrab(7);
492         }
493         assert(bitcount ==
494                61 + 130 * rtcm->rtcmtypes.rtcm3_1012.header.satcount);
495         break;
496
497     case 1013:                  /* System Parameters */
498         rtcm->rtcmtypes.rtcm3_1013.station_id = (unsigned short)ugrab(12);
499         rtcm->rtcmtypes.rtcm3_1013.mjd = (unsigned short)ugrab(16);
500         rtcm->rtcmtypes.rtcm3_1013.sod = (unsigned short)ugrab(17);
501         rtcm->rtcmtypes.rtcm3_1013.ncount = (unsigned long)ugrab(5);
502         rtcm->rtcmtypes.rtcm3_1013.leapsecs = (unsigned char)ugrab(8);
503         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1013.ncount; i++) {
504             rtcm->rtcmtypes.rtcm3_1013.announcements[i].id =
505                 (unsigned short)ugrab(12);
506             rtcm->rtcmtypes.rtcm3_1013.announcements[i].sync =
507                 (bool) ugrab(1);
508             rtcm->rtcmtypes.rtcm3_1013.announcements[i].interval =
509                 (unsigned short)ugrab(16);
510         }
511         assert(bitcount == 70 + 29 * rtcm->rtcmtypes.rtcm3_1013.ncount);
512         break;
513
514     case 1014:
515         rtcm->rtcmtypes.rtcm3_1014.network_id = (int)ugrab(8);
516         rtcm->rtcmtypes.rtcm3_1014.subnetwork_id = (int)ugrab(4);
517         rtcm->rtcmtypes.rtcm3_1014.stationcount = (char)ugrab(5);
518         rtcm->rtcmtypes.rtcm3_1014.master_id = (int)ugrab(12);
519         rtcm->rtcmtypes.rtcm3_1014.aux_id = (int)ugrab(12);
520         rtcm->rtcmtypes.rtcm3_1014.d_lat =
521             (unsigned short)ugrab(20) * ANTENNA_DEGREE_RESOLUTION;
522         rtcm->rtcmtypes.rtcm3_1014.d_lon =
523             (unsigned short)ugrab(21) * ANTENNA_DEGREE_RESOLUTION;
524         rtcm->rtcmtypes.rtcm3_1014.d_alt = (unsigned short)ugrab(23) / 1000;
525         assert(bitcount == 117);
526         break;
527
528     case 1015:
529         break;
530
531     case 1016:
532         break;
533
534     case 1017:
535         break;
536
537     case 1018:
538         break;
539
540     case 1019:
541         break;
542
543     case 1020:
544         break;
545
546     case 1029:
547         rtcm->rtcmtypes.rtcm3_1029.station_id = (unsigned short)ugrab(12);
548         rtcm->rtcmtypes.rtcm3_1029.mjd = (unsigned short)ugrab(16);
549         rtcm->rtcmtypes.rtcm3_1029.sod = (unsigned short)ugrab(17);
550         rtcm->rtcmtypes.rtcm3_1029.len = (unsigned long)ugrab(7);
551         n = rtcm->rtcmtypes.rtcm3_1029.unicode_units =
552             (unsigned long)ugrab(8);
553         (void)memcpy(rtcm->rtcmtypes.rtcm3_1029.text, buf + 9, n);
554         bitcount += 8 * n;
555         assert(bitcount == (int)(72 + 8 * n));
556         break;
557     }
558 #undef sgrab
559 #undef ugrab
560     /*@ +evalorder +sefparams +mayaliasunique @*/
561 }
562
563 void rtcm3_dump(struct rtcm3_t *rtcm, FILE * fp)
564 /* dump the contents of a parsed RTCM104 message */
565 {
566     int i;
567
568     char *systems[] = { "GPS", "Glonass", "Galileo", "unknown" };
569
570     (void)fprintf(fp, "%u (%u):\n", rtcm->type, rtcm->length);
571
572 #define BOOL(c) (c!=0 ? 't' : 'f')
573 #define CODE(x) (unsigned int)(x)
574 #define INT(x) (unsigned int)(x)
575     switch (rtcm->type) {
576     case 1001:
577         (void)fprintf(fp,
578                       "  #station_id=%u, tow=%d sync=%c smoothing=%c interval=%u satcount=%u",
579                       rtcm->rtcmtypes.rtcm3_1001.header.station_id,
580                       (int)rtcm->rtcmtypes.rtcm3_1001.header.tow,
581                       BOOL(rtcm->rtcmtypes.rtcm3_1001.header.sync),
582                       BOOL(rtcm->rtcmtypes.rtcm3_1001.header.smoothing),
583                       rtcm->rtcmtypes.rtcm3_1001.header.interval,
584                       rtcm->rtcmtypes.rtcm3_1001.header.satcount);
585         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1001.header.satcount; i++) {
586             (void)fprintf(fp,
587                           "    ident=%u\n      L1: ind=%u prange=%8.1f delta=%6.4f lockt=%u\n",
588                           rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].ident,
589                           CODE(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
590                                L1.indicator),
591                           rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].
592                           L1.pseudorange,
593                           rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].L1.rangediff,
594                           INT(rtcm->rtcmtypes.rtcm3_1001.rtk_data[i].
595                               L1.locktime));
596         }
597         break;
598
599     case 1002:
600         (void)fprintf(fp,
601                       "  #station_id=%u, tow=%d sync=%c smoothing=%c interval=%u satcount=%u",
602                       rtcm->rtcmtypes.rtcm3_1002.header.station_id,
603                       (int)rtcm->rtcmtypes.rtcm3_1002.header.tow,
604                       BOOL(rtcm->rtcmtypes.rtcm3_1002.header.sync),
605                       BOOL(rtcm->rtcmtypes.rtcm3_1002.header.smoothing),
606                       rtcm->rtcmtypes.rtcm3_1002.header.interval,
607                       rtcm->rtcmtypes.rtcm3_1002.header.satcount);
608         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1002.header.satcount; i++) {
609             (void)fprintf(fp,
610                           "    ident=%u\n      L1: ind=%u prange=%8.1f delta=%6.4f lockt=%u amb=%u CNR=%.2f\n",
611                           rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].ident,
612                           CODE(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
613                                L1.indicator),
614                           rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].
615                           L1.pseudorange,
616                           rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.rangediff,
617                           INT(rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].
618                               L1.locktime),
619                           INT(rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].
620                               L1.ambiguity),
621                           rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.CNR);
622         }
623         break;
624
625     case 1003:
626         (void)fprintf(fp,
627                       "  #station_id=%u, tow=%d sync=%c smoothing=%c interval=%u satcount=%u",
628                       rtcm->rtcmtypes.rtcm3_1003.header.station_id,
629                       (int)rtcm->rtcmtypes.rtcm3_1003.header.tow,
630                       BOOL(rtcm->rtcmtypes.rtcm3_1003.header.sync),
631                       BOOL(rtcm->rtcmtypes.rtcm3_1003.header.smoothing),
632                       rtcm->rtcmtypes.rtcm3_1003.header.interval,
633                       rtcm->rtcmtypes.rtcm3_1003.header.satcount);
634         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1003.header.satcount; i++) {
635             (void)fprintf(fp,
636                           "    ident=%u\n      L1: ind=%u prange=%8.1f delta=%6.4f lockt=%u\n      L2: ind=%u prange=%8.1f delta=%6.4f lockt=%u\n",
637                           rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].ident,
638                           CODE(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
639                                L1.indicator),
640                           rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
641                           L1.pseudorange,
642                           rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L1.rangediff,
643                           INT(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
644                               L1.locktime),
645                           CODE(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
646                                L2.indicator),
647                           rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
648                           L2.pseudorange,
649                           rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].L2.rangediff,
650                           INT(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
651                               L2.locktime));
652         }
653         break;
654
655     case 1004:
656         (void)fprintf(fp,
657                       "  #station_id=%u, tow=%d sync=%c smoothing=%c interval=%u satcount=%u\n",
658                       rtcm->rtcmtypes.rtcm3_1004.header.station_id,
659                       (int)rtcm->rtcmtypes.rtcm3_1004.header.tow,
660                       BOOL(rtcm->rtcmtypes.rtcm3_1004.header.sync),
661                       BOOL(rtcm->rtcmtypes.rtcm3_1004.header.smoothing),
662                       rtcm->rtcmtypes.rtcm3_1004.header.interval,
663                       rtcm->rtcmtypes.rtcm3_1004.header.satcount);
664         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1004.header.satcount; i++) {
665             (void)fprintf(fp,
666                           "    ident=%u\n      L1: ind=%u prange=%8.1f delta=%6.4f lockt=%u amb=%u CNR=%.2f\n      L2: ind=%u prange=%8.1f delta=%6.4f lockt=%u amb=%u CNR=%.2f\n",
667                           rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].ident,
668                           CODE(rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
669                                L1.indicator),
670                           rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
671                           L1.pseudorange,
672                           rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L1.rangediff,
673                           INT(rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
674                               L1.locktime),
675                           INT(rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].
676                               L1.ambiguity),
677                           rtcm->rtcmtypes.rtcm3_1002.rtk_data[i].L1.CNR,
678                           CODE(rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
679                                L2.indicator),
680                           rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
681                           L2.pseudorange,
682                           rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.rangediff,
683                           INT(rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
684                               L2.locktime),
685                           INT(rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].
686                               L2.ambiguity),
687                           rtcm->rtcmtypes.rtcm3_1004.rtk_data[i].L2.CNR);
688         }
689         break;
690
691     case 1005:
692         (void)fprintf(fp,
693                       "  station_id=%u, %s refstation=%c sro=%c x=%f y=%f z=%f\n",
694                       rtcm->rtcmtypes.rtcm3_1005.station_id,
695                       systems[rtcm->rtcmtypes.rtcm3_1005.system],
696                       BOOL(rtcm->rtcmtypes.rtcm3_1005.reference_station),
697                       BOOL(rtcm->rtcmtypes.rtcm3_1005.single_receiver),
698                       rtcm->rtcmtypes.rtcm3_1005.ecef_x,
699                       rtcm->rtcmtypes.rtcm3_1005.ecef_y,
700                       rtcm->rtcmtypes.rtcm3_1005.ecef_z);
701         break;
702
703     case 1006:
704         (void)fprintf(fp,
705                       "  station_id=%u, %s refstation=%c sro=%c x=%f y=%f z=%f a=%f\n",
706                       rtcm->rtcmtypes.rtcm3_1006.station_id,
707                       systems[rtcm->rtcmtypes.rtcm3_1006.system],
708                       BOOL(rtcm->rtcmtypes.rtcm3_1006.reference_station),
709                       BOOL(rtcm->rtcmtypes.rtcm3_1006.single_receiver),
710                       rtcm->rtcmtypes.rtcm3_1006.ecef_x,
711                       rtcm->rtcmtypes.rtcm3_1006.ecef_y,
712                       rtcm->rtcmtypes.rtcm3_1006.ecef_z,
713                       rtcm->rtcmtypes.rtcm3_1006.height);
714         break;
715
716     case 1007:
717         (void)fprintf(fp,
718                       "  station_id=%u, desc=%s setup-id=%u\n",
719                       rtcm->rtcmtypes.rtcm3_1007.station_id,
720                       rtcm->rtcmtypes.rtcm3_1007.descriptor,
721                       INT(rtcm->rtcmtypes.rtcm3_1007.setup_id));
722         break;
723
724     case 1008:
725         (void)fprintf(fp,
726                       "  station_id=%u, desc=%s setup-id=%u serial=%s\n",
727                       rtcm->rtcmtypes.rtcm3_1008.station_id,
728                       rtcm->rtcmtypes.rtcm3_1008.descriptor,
729                       INT(rtcm->rtcmtypes.rtcm3_1008.setup_id),
730                       rtcm->rtcmtypes.rtcm3_1008.serial);
731         break;
732
733     case 1009:
734         (void)fprintf(fp,
735                       "  #station_id=%u, tow=%d sync=%c smooting=%c interval=%u satcount=%u",
736                       rtcm->rtcmtypes.rtcm3_1009.header.station_id,
737                       (int)rtcm->rtcmtypes.rtcm3_1009.header.tow,
738                       BOOL(rtcm->rtcmtypes.rtcm3_1009.header.sync),
739                       BOOL(rtcm->rtcmtypes.rtcm3_1009.header.smoothing),
740                       rtcm->rtcmtypes.rtcm3_1009.header.interval,
741                       rtcm->rtcmtypes.rtcm3_1009.header.satcount);
742         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1009.header.satcount; i++) {
743             (void)fprintf(fp,
744                           "    ident=%u\n      L1: ind=%u channel=%u prange=%8.1f delta=%6.4f lockt=%u\n",
745                           rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].ident,
746                           CODE(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
747                                L1.indicator),
748                           INT(rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].
749                               L1.channel),
750                           rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].
751                           L1.pseudorange,
752                           rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].L1.rangediff,
753                           INT(rtcm->rtcmtypes.rtcm3_1009.rtk_data[i].
754                               L1.locktime));
755         }
756         break;
757
758     case 1010:
759         (void)fprintf(fp,
760                       "  #station_id=%u, tow=%d sync=%c smooting=%c interval=%u satcount=%u",
761                       rtcm->rtcmtypes.rtcm3_1010.header.station_id,
762                       (int)rtcm->rtcmtypes.rtcm3_1010.header.tow,
763                       BOOL(rtcm->rtcmtypes.rtcm3_1010.header.sync),
764                       BOOL(rtcm->rtcmtypes.rtcm3_1010.header.smoothing),
765                       rtcm->rtcmtypes.rtcm3_1010.header.interval,
766                       rtcm->rtcmtypes.rtcm3_1010.header.satcount);
767         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1010.header.satcount; i++) {
768             (void)fprintf(fp,
769                           "    ident=%u\n      L1: ind=%u channel=%u prange=%8.1f delta=%6.4f lockt=%u amb=%u CNR=%.2f\n",
770                           rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].ident,
771                           CODE(rtcm->rtcmtypes.rtcm3_1003.rtk_data[i].
772                                L1.indicator),
773                           INT(rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].
774                               L1.channel),
775                           rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].
776                           L1.pseudorange,
777                           rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.rangediff,
778                           INT(rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].
779                               L1.locktime),
780                           INT(rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].
781                               L1.ambiguity),
782                           rtcm->rtcmtypes.rtcm3_1010.rtk_data[i].L1.CNR);
783         }
784         break;
785
786     case 1011:
787         (void)fprintf(fp,
788                       "  #station_id=%u, tow=%d sync=%c smooting=%c interval=%u satcount=%u",
789                       rtcm->rtcmtypes.rtcm3_1011.header.station_id,
790                       (int)rtcm->rtcmtypes.rtcm3_1011.header.tow,
791                       BOOL(rtcm->rtcmtypes.rtcm3_1011.header.sync),
792                       BOOL(rtcm->rtcmtypes.rtcm3_1011.header.smoothing),
793                       rtcm->rtcmtypes.rtcm3_1011.header.interval,
794                       rtcm->rtcmtypes.rtcm3_1011.header.satcount);
795         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1011.header.satcount; i++) {
796             (void)fprintf(fp,
797                           "    ident=%u\n      L1: ind=%u channel=%u prange=%8.1f delta=%6.4f lockt=%u\n      L2: ind=%u prange=%8.1f delta=%6.4f lockt=%u\n",
798                           rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].ident,
799                           CODE(rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
800                                L1.indicator),
801                           INT(rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
802                               L1.channel),
803                           rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
804                           L1.pseudorange,
805                           rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L1.rangediff,
806                           INT(rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
807                               L1.locktime),
808                           CODE(rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
809                                L2.indicator),
810                           rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
811                           L2.pseudorange,
812                           rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].L2.rangediff,
813                           INT(rtcm->rtcmtypes.rtcm3_1011.rtk_data[i].
814                               L2.locktime));
815         }
816         break;
817
818     case 1012:
819         (void)fprintf(fp,
820                       "  #station_id=%u, tow=%d sync=%c smooting=%c interval=%u satcount=%u",
821                       rtcm->rtcmtypes.rtcm3_1012.header.station_id,
822                       (int)rtcm->rtcmtypes.rtcm3_1012.header.tow,
823                       BOOL(rtcm->rtcmtypes.rtcm3_1012.header.sync),
824                       BOOL(rtcm->rtcmtypes.rtcm3_1012.header.smoothing),
825                       rtcm->rtcmtypes.rtcm3_1012.header.interval,
826                       rtcm->rtcmtypes.rtcm3_1012.header.satcount);
827         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1012.header.satcount; i++) {
828             (void)fprintf(fp,
829                           "    ident=%u\n      L1: ind=%u channel=%u prange=%8.1f delta=%6.4f lockt=%u amb=%u CNR=%.2f\n      L2: ind=%u prange=%8.1f delta=%6.4f lockt=%u amb=%u CNR=%.2f\n",
830                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].ident,
831                           CODE(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
832                                L1.indicator),
833                           INT(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
834                               L1.channel),
835                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
836                           L1.pseudorange,
837                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.rangediff,
838                           INT(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
839                               L1.locktime),
840                           INT(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
841                               L1.ambiguity),
842                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L1.CNR,
843                           CODE(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
844                                L2.indicator),
845                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
846                           L2.pseudorange,
847                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.rangediff,
848                           INT(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
849                               L2.locktime),
850                           INT(rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].
851                               L2.ambiguity),
852                           rtcm->rtcmtypes.rtcm3_1012.rtk_data[i].L2.CNR);
853         }
854         break;
855
856     case 1013:
857         (void)fprintf(fp,
858                       "  station_id=%u, mjd=%u sec=%u leapsecs=%u ncount=%u\n",
859                       rtcm->rtcmtypes.rtcm3_1013.station_id,
860                       rtcm->rtcmtypes.rtcm3_1013.mjd,
861                       rtcm->rtcmtypes.rtcm3_1013.sod,
862                       INT(rtcm->rtcmtypes.rtcm3_1013.leapsecs),
863                       INT(rtcm->rtcmtypes.rtcm3_1013.ncount));
864         for (i = 0; i < rtcm->rtcmtypes.rtcm3_1013.ncount; i++)
865             (void)fprintf(fp,
866                           "    id=%u sync=%c interval=%u\n",
867                           rtcm->rtcmtypes.rtcm3_1013.announcements[i].id,
868                           BOOL(rtcm->rtcmtypes.rtcm3_1013.
869                                announcements[i].sync),
870                           rtcm->rtcmtypes.rtcm3_1013.
871                           announcements[i].interval);
872         break;
873
874     case 1014:
875         (void)fprintf(fp,
876                       "    netid=%u subnetid=%u statcount=%u master=%u aux=%u lat=%f, lon=%f, alt=%f\n",
877                       rtcm->rtcmtypes.rtcm3_1014.network_id,
878                       rtcm->rtcmtypes.rtcm3_1014.subnetwork_id,
879                       (uint) rtcm->rtcmtypes.rtcm3_1014.stationcount,
880                       rtcm->rtcmtypes.rtcm3_1014.master_id,
881                       rtcm->rtcmtypes.rtcm3_1014.aux_id,
882                       rtcm->rtcmtypes.rtcm3_1014.d_lat,
883                       rtcm->rtcmtypes.rtcm3_1014.d_lon,
884                       rtcm->rtcmtypes.rtcm3_1014.d_alt);
885         break;
886
887     case 1015:
888         break;
889
890     case 1016:
891         break;
892
893     case 1017:
894         break;
895
896     case 1018:
897         break;
898
899     case 1019:
900         break;
901
902     case 1020:
903         break;
904
905     case 1029:
906         (void)fprintf(fp,
907                       "  station_id=%u, mjd=%u sec=%u len=%u units=%u msg=%s\n",
908                       rtcm->rtcmtypes.rtcm3_1029.station_id,
909                       rtcm->rtcmtypes.rtcm3_1029.mjd,
910                       rtcm->rtcmtypes.rtcm3_1029.sod,
911                       INT(rtcm->rtcmtypes.rtcm3_1029.len),
912                       INT(rtcm->rtcmtypes.rtcm3_1029.unicode_units),
913                       (char *)rtcm->rtcmtypes.rtcm3_1029.text);
914         break;
915
916     default:
917         (void)fprintf(fp, "    Unknown content\n");
918         break;
919     }
920 #undef CODE
921 #undef BOOL
922 #undef INT
923 }
924
925 /* *INDENT-ON* */
926 /*@ +type @*/
927
928 #endif /* RTCM104V3_ENABLE */