source: ntrip/trunk/rtcm3torinex/lib/rtcm3torinex.c@ 6538

Last change on this file since 6538 was 6538, checked in by stoecker, 9 years ago

new leap second comes

  • Property svn:keywords set to Id Revision Date
File size: 140.8 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 6538 2015-01-05 14:52:38Z stoecker $
4 Copyright (C) 2005-2012 by Dirk Stöcker <stoecker@alberding.eu>
5
6 This software is a complete NTRIP-RTCM3 to RINEX converter as well as
7 a module of the BNC tool for multiformat conversion. Contact Dirk
8 Stöcker for suggestions and bug reports related to the RTCM3 to RINEX
9 conversion problems and the author of BNC for all the other problems.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 or read http://www.gnu.org/licenses/gpl.txt
25*/
26
27#include <ctype.h>
28#include <errno.h>
29#include <math.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/types.h>
36#include <time.h>
37#include <unistd.h>
38
39#ifndef NO_RTCM3_MAIN
40#include <getopt.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#endif
45
46#ifndef sparc
47#include <stdint.h>
48#endif
49
50#ifndef isinf
51#define isinf(x) 0
52#endif
53
54#include "rtcm3torinex.h"
55
56/* CVS revision and version */
57static char revisionstr[] = "$Revision: 6538 $";
58
59#ifndef COMPILEDATE
60#define COMPILEDATE " built " __DATE__
61#endif
62
63static uint32_t CRC24(long size, const unsigned char *buf)
64{
65 uint32_t crc = 0;
66 int i;
67
68 while(size--)
69 {
70 crc ^= (*buf++) << (16);
71 for(i = 0; i < 8; i++)
72 {
73 crc <<= 1;
74 if(crc & 0x1000000)
75 crc ^= 0x01864cfb;
76 }
77 }
78 return crc;
79}
80
81static int GetMessage(struct RTCM3ParserData *handle)
82{
83 unsigned char *m, *e;
84 int i;
85
86 m = handle->Message+handle->SkipBytes;
87 e = handle->Message+handle->MessageSize;
88 handle->NeedBytes = handle->SkipBytes = 0;
89 while(e-m >= 3)
90 {
91 if(m[0] == 0xD3)
92 {
93 handle->size = ((m[1]&3)<<8)|m[2];
94 if(e-m >= handle->size+6)
95 {
96 if((uint32_t)((m[3+handle->size]<<16)|(m[3+handle->size+1]<<8)
97 |(m[3+handle->size+2])) == CRC24(handle->size+3, m))
98 {
99 handle->SkipBytes = handle->size;
100 break;
101 }
102 else
103 ++m;
104 }
105 else
106 {
107 handle->NeedBytes = handle->size+6;
108 break;
109 }
110 }
111 else
112 ++m;
113 }
114 if(e-m < 3)
115 handle->NeedBytes = 3;
116
117 /* copy buffer to front */
118 i = m - handle->Message;
119 if(i && m < e)
120 memmove(handle->Message, m, (size_t)(handle->MessageSize-i));
121 handle->MessageSize -= i;
122
123 return !handle->NeedBytes;
124}
125
126#define LOADBITS(a) \
127{ \
128 while((a) > numbits) \
129 { \
130 if(!size--) break; \
131 bitfield = (bitfield<<8)|*(data++); \
132 numbits += 8; \
133 } \
134}
135
136/* extract bits from data stream
137 b = variable to store result, a = number of bits */
138#define GETBITS64(b, a) \
139{ \
140 if(((a) > 56) && ((a)-56) > numbits) \
141 { \
142 uint64_t x; \
143 GETBITS(x, 56) \
144 LOADBITS((a)-56) \
145 b = ((x<<((a)-56)) | (bitfield<<(sizeof(bitfield)*8-numbits)) \
146 >>(sizeof(bitfield)*8-((a)-56))); \
147 numbits -= ((a)-56); \
148 } \
149 else \
150 { \
151 GETBITS(b, a) \
152 } \
153}
154
155/* extract bits from data stream
156 b = variable to store result, a = number of bits */
157#define GETBITS(b, a) \
158{ \
159 LOADBITS(a) \
160 b = (bitfield<<(64-numbits))>>(64-(a)); \
161 numbits -= (a); \
162}
163
164/* extract bits from data stream
165 b = variable to store result, a = number of bits */
166#define GETBITSFACTOR(b, a, c) \
167{ \
168 LOADBITS(a) \
169 b = ((bitfield<<(sizeof(bitfield)*8-numbits))>>(sizeof(bitfield)*8-(a)))*(c); \
170 numbits -= (a); \
171}
172
173/* extract floating value from data stream
174 b = variable to store result, a = number of bits */
175#define GETFLOAT(b, a, c) \
176{ \
177 LOADBITS(a) \
178 b = ((double)((bitfield<<(64-numbits))>>(64-(a))))*(c); \
179 numbits -= (a); \
180}
181
182/* extract signed floating value from data stream
183 b = variable to store result, a = number of bits */
184#define GETFLOATSIGN(b, a, c) \
185{ \
186 LOADBITS(a) \
187 b = ((double)(((int64_t)(bitfield<<(64-numbits)))>>(64-(a))))*(c); \
188 numbits -= (a); \
189}
190
191/* extract bits from data stream
192 b = variable to store result, a = number of bits */
193#define GETBITSSIGN(b, a) \
194{ \
195 LOADBITS(a) \
196 b = ((int64_t)(bitfield<<(64-numbits)))>>(64-(a)); \
197 numbits -= (a); \
198}
199
200#define GETFLOATSIGNM(b, a, c) \
201{ int l; \
202 LOADBITS(a) \
203 l = (bitfield<<(64-numbits))>>(64-1); \
204 b = ((double)(((bitfield<<(64-(numbits-1))))>>(64-(a-1))))*(c); \
205 numbits -= (a); \
206 if(l) b *= -1.0; \
207}
208
209#define SKIPBITS(b) { LOADBITS(b) numbits -= (b); }
210
211/* extract byte-aligned byte from data stream,
212 b = variable to store size, s = variable to store string pointer */
213#define GETSTRING(b, s) \
214{ \
215 b = *(data++); \
216 s = (char *) data; \
217 data += b; \
218 size -= b+1; \
219}
220
221struct leapseconds { /* specify the day of leap second */
222 int day; /* this is the day, where 23:59:59 exists 2 times */
223 int month; /* not the next day! */
224 int year;
225 int taicount;
226};
227static const int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
228static const struct leapseconds leap[] = {
229/*{31, 12, 1971, 10},*/
230/*{30, 06, 1972, 11},*/
231/*{31, 12, 1972, 12},*/
232/*{31, 12, 1973, 13},*/
233/*{31, 12, 1974, 14},*/
234/*{31, 12, 1975, 15},*/
235/*{31, 12, 1976, 16},*/
236/*{31, 12, 1977, 17},*/
237/*{31, 12, 1978, 18},*/
238/*{31, 12, 1979, 19},*/
239{30, 06, 1981,20},
240{30, 06, 1982,21},
241{30, 06, 1983,22},
242{30, 06, 1985,23},
243{31, 12, 1987,24},
244{31, 12, 1989,25},
245{31, 12, 1990,26},
246{30, 06, 1992,27},
247{30, 06, 1993,28},
248{30, 06, 1994,29},
249{31, 12, 1995,30},
250{30, 06, 1997,31},
251{31, 12, 1998,32},
252{31, 12, 2005,33},
253{31, 12, 2008,34},
254{30, 06, 2012,35},
255{30, 06, 2015,36},
256{0,0,0,0} /* end marker */
257};
258#define LEAPSECONDS 17 /* only needed for approx. time */
259#define GPSLEAPSTART 19 /* 19 leap seconds existed at 6.1.1980 */
260
261static int longyear(int year, int month)
262{
263 if(!(year % 4) && (!(year % 400) || (year % 100)))
264 {
265 if(!month || month == 2)
266 return 1;
267 }
268 return 0;
269}
270
271int gnumleap(int year, int month, int day)
272{
273 int ls = 0;
274 const struct leapseconds *l;
275
276 for(l = leap; l->taicount && year >= l->year; ++l)
277 {
278 if(year > l->year || month > l->month || (month == l->month && day > l->day))
279 ls = l->taicount - GPSLEAPSTART;
280 }
281 return ls;
282}
283
284/* Convert Moscow time into UTC (fixnumleap == 1) or GPS (fixnumleap == 0) */
285void updatetime(int *week, int *secOfWeek, int mSecOfWeek, int fixnumleap)
286{
287 int y,m,d,k,l, nul;
288 unsigned int j = *week*(7*24*60*60) + *secOfWeek + 5*24*60*60+3*60*60;
289 int glo_daynumber = 0, glo_timeofday;
290 for(y = 1980; j >= (unsigned int)(k = (l = (365+longyear(y,0)))*24*60*60)
291 + gnumleap(y+1,1,1); ++y)
292 {
293 j -= k; glo_daynumber += l;
294 }
295 for(m = 1; j >= (unsigned int)(k = (l = months[m]+longyear(y, m))*24*60*60)
296 + gnumleap(y, m+1, 1); ++m)
297 {
298 j -= k; glo_daynumber += l;
299 }
300 for(d = 1; j >= 24UL*60UL*60UL + gnumleap(y, m, d+1); ++d)
301 j -= 24*60*60;
302 glo_daynumber -= 16*365+4-d;
303 nul = gnumleap(y, m, d);
304 glo_timeofday = j-nul;
305
306 // original version
307 // if(mSecOfWeek < 5*60*1000 && glo_timeofday > 23*60*60)
308 // *secOfWeek += 24*60*60;
309 // else if(glo_timeofday < 5*60 && mSecOfWeek > 23*60*60*1000)
310 // *secOfWeek -= 24*60*60;
311
312 // new version
313 if(mSecOfWeek < 4*60*60*1000 && glo_timeofday > 20*60*60)
314 *secOfWeek += 24*60*60;
315 else if(glo_timeofday < 4*60*60 && mSecOfWeek > 20*60*60*1000)
316 *secOfWeek -= 24*60*60;
317
318 *secOfWeek += mSecOfWeek/1000-glo_timeofday;
319 if(fixnumleap)
320 *secOfWeek -= nul;
321 if(*secOfWeek < 0) {*secOfWeek += 24*60*60*7; --*week; }
322 if(*secOfWeek >= 24*60*60*7) {*secOfWeek -= 24*60*60*7; ++*week; }
323}
324
325int RTCM3Parser(struct RTCM3ParserData *handle)
326{
327 int ret=0;
328
329#ifdef NO_RTCM3_MAIN
330 if(GetMessage(handle)) /* don't repeat */
331#else
332 while(!ret && GetMessage(handle))
333#endif /* NO_RTCM3_MAIN */
334 {
335 /* using 64 bit integer types, as it is much easier than handling
336 the long datatypes in 32 bit */
337 uint64_t numbits = 0, bitfield = 0;
338 int size = handle->size, type;
339 int syncf, old = 0;
340 unsigned char *data = handle->Message+3;
341
342 GETBITS(type,12)
343#ifdef NO_RTCM3_MAIN
344 handle->blocktype = type;
345#endif /* NO_RTCM3_MAIN */
346 switch(type)
347 {
348#ifdef NO_RTCM3_MAIN
349 default:
350 ret = type;
351 break;
352 case 1005: case 1006:
353 {
354 SKIPBITS(22)
355 GETBITSSIGN(handle->antX, 38)
356 SKIPBITS(2)
357 GETBITSSIGN(handle->antY, 38)
358 SKIPBITS(2)
359 GETBITSSIGN(handle->antZ, 38)
360 if(type == 1006)
361 GETBITS(handle->antH, 16)
362 ret = type;
363 }
364 break;
365 case 1007: case 1008: case 1033:
366 {
367 char *antenna;
368 int antnum;
369
370 SKIPBITS(12)
371 GETSTRING(antnum,antenna)
372 memcpy(handle->antenna, antenna, antnum);
373 handle->antenna[antnum] = 0;
374 ret = type;
375 }
376 break;
377 case 1013:
378 {
379 SKIPBITS(12);
380 GETBITS(handle->modjulday, 16);
381 GETBITS(handle->secofday, 17);
382 SKIPBITS(5);
383 GETBITS(handle->leapsec, 8);
384 ret = 1013;
385 }
386 break;
387#endif /* NO_RTCM3_MAIN */
388 case 1019:
389 {
390 struct gpsephemeris *ge;
391 int sv, i;
392
393 ge = &handle->ephemerisGPS;
394 memset(ge, 0, sizeof(*ge));
395
396 GETBITS(sv, 6)
397 ge->satellite = (sv < 40 ? sv : sv+80);
398 GETBITS(ge->GPSweek, 10)
399 ge->GPSweek += 1024;
400 GETBITS(ge->URAindex, 4)
401 GETBITS(sv, 2)
402 if(sv & 1)
403 ge->flags |= GPSEPHF_L2PCODE;
404 if(sv & 2)
405 ge->flags |= GPSEPHF_L2CACODE;
406 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
407 GETBITS(ge->IODE, 8)
408 GETBITS(ge->TOC, 16)
409 ge->TOC <<= 4;
410 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
411 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
412 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
413 GETBITS(ge->IODC, 10)
414 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
415 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
416 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
417 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
418 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
419 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
420 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
421 GETBITS(ge->TOE, 16)
422 ge->TOE <<= 4;
423
424 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
425 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
426 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
427 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
428 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
429 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
430 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
431 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
432 GETBITS(ge->SVhealth, 6)
433 GETBITS(sv, 1)
434 if(sv)
435 ge->flags |= GPSEPHF_L2PCODEDATA;
436 GETBITS(sv, 1)
437 if(sv)
438 ge->flags |= GPSEPHF_6HOURSFIT;
439
440 i = ((int)ge->GPSweek - (int)handle->GPSWeek)*7*24*60*60
441 + ((int)ge->TOE - (int)handle->GPSTOW) - 2*60*60;
442 if(i > 5*60*60 && i < 8*60*60)
443 {
444 handle->GPSTOW = ge->TOE;
445 handle->GPSWeek = ge->GPSweek;
446 }
447 ge->TOW = 0.9999E9;
448 ret = 1019;
449 }
450 break;
451 case 1043:
452 if(handle->GPSWeek)
453 {
454 struct sbasephemeris *gs;
455 int sv, i, time, tod, day;
456 gs = &handle->ephemerisSBAS;
457 memset(gs, 0, sizeof(*gs));
458
459 GETBITS(sv, 6)
460 gs->satellite = PRN_SBAS_START+sv;
461 GETBITS(gs->IODN, 8)
462 GETBITS(time, 13)
463 time <<= 4;
464 gs->GPSweek_TOE = handle->GPSWeek;
465 GETBITS(gs->URA, 4)
466 GETFLOATSIGN(gs->x_pos, 30, 0.08)
467 GETFLOATSIGN(gs->y_pos, 30, 0.08)
468 GETFLOATSIGN(gs->z_pos, 25, 0.4)
469 GETFLOATSIGN(gs->x_velocity, 17, 0.000625)
470 GETFLOATSIGN(gs->y_velocity, 17, 0.000625)
471 GETFLOATSIGN(gs->z_velocity, 18, 0.004)
472 GETFLOATSIGN(gs->x_acceleration, 10, 0.0000125)
473 GETFLOATSIGN(gs->y_acceleration, 10, 0.0000125)
474 GETFLOATSIGN(gs->z_acceleration, 10, 0.0000625)
475 GETFLOATSIGN(gs->agf0, 12, 1.0/(1<<30)/(1<<1))
476 GETFLOATSIGN(gs->agf1, 8, 1.0/(1<<30)/(1<<10))
477
478 /* calculate time */
479 tod = handle->GPSTOW%(24*60*60);
480 day = handle->GPSTOW/(24*60*60);
481 if(time > 19*60*60 && tod < 5*60*60)
482 --day;
483 else if(time < 5*60*60 && tod > 19*60*60)
484 ++day;
485 time += day*24*60*60;
486 if(time > 7*24*60*60)
487 ++gs->GPSweek_TOE;
488 else if(time < 0)
489 --gs->GPSweek_TOE;
490 gs->TOE = time;
491
492 i = (gs->GPSweek_TOE - handle->GPSWeek)*7*24*60*60
493 + (gs->TOE - handle->GPSTOW) - 2*60*60;
494 if(i > 5*60*60 && i < 8*60*60)
495 {
496 handle->GPSTOW = gs->TOE;
497 handle->GPSWeek = gs->GPSweek_TOE;
498 }
499 gs->TOW = 0.9999E9;
500 ret = 1043;
501 }
502 break;
503 case 1044:
504 {
505 struct gpsephemeris *ge;
506 int sv, i;
507
508 ge = &handle->ephemerisGPS;
509 memset(ge, 0, sizeof(*ge));
510
511 GETBITS(sv, 4)
512 ge->satellite = PRN_QZSS_START+sv-1;
513 GETBITS(ge->TOC, 16)
514 ge->TOC <<= 4;
515 GETFLOATSIGN(ge->clock_driftrate, 8, 1.0/(double)(1<<30)/(double)(1<<25))
516 GETFLOATSIGN(ge->clock_drift, 16, 1.0/(double)(1<<30)/(double)(1<<13))
517 GETFLOATSIGN(ge->clock_bias, 22, 1.0/(double)(1<<30)/(double)(1<<1))
518 GETBITS(ge->IODE, 8)
519 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
520 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
521 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
522 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
523 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
524 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
525 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
526 GETBITS(ge->TOE, 16)
527 ge->TOE <<= 4;
528 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
529 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
530 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
531 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
532 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
533 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
534 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
535 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
536 GETBITS(sv, 2)
537 if(sv & 1)
538 ge->flags |= GPSEPHF_L2PCODE;
539 if(sv & 2)
540 ge->flags |= GPSEPHF_L2CACODE;
541 GETBITS(ge->GPSweek, 10)
542 ge->GPSweek += 1024;
543 GETBITS(ge->URAindex, 4)
544 GETBITS(ge->SVhealth, 6)
545 GETFLOATSIGN(ge->TGD, 8, 1.0/(double)(1<<30)/(double)(1<<1))
546 GETBITS(ge->IODC, 10)
547 GETBITS(sv, 1)
548 if(sv)
549 ge->flags |= GPSEPHF_6HOURSFIT;
550
551 i = ((int)ge->GPSweek - (int)handle->GPSWeek)*7*24*60*60
552 + ((int)ge->TOE - (int)handle->GPSTOW) - 2*60*60;
553 if(i > 5*60*60 && i < 8*60*60)
554 {
555 handle->GPSTOW = ge->TOE;
556 handle->GPSWeek = ge->GPSweek;
557 }
558 ge->TOW = 0.9999E9;
559 ret = 1044;
560 }
561 break;
562 case 1045: case 1046:
563 {
564 struct galileoephemeris *ge;
565 int sv;
566
567 ge = &handle->ephemerisGALILEO;
568 memset(ge, 0, sizeof(*ge));
569
570 GETBITS(sv, 6)
571 ge->satellite = sv;
572 GETBITS(ge->Week, 12)
573 GETBITS(ge->IODnav, 10)
574 GETBITS(ge->SISA, 8)
575 GETFLOATSIGN(ge->IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
576 GETBITSFACTOR(ge->TOC, 14, 60)
577 GETFLOATSIGN(ge->clock_driftrate, 6, 1.0/(double)(1<<30)/(double)(1<<29))
578 GETFLOATSIGN(ge->clock_drift, 21, 1.0/(double)(1<<30)/(double)(1<<16))
579 GETFLOATSIGN(ge->clock_bias, 31, 1.0/(double)(1<<30)/(double)(1<<4))
580 GETFLOATSIGN(ge->Crs, 16, 1.0/(double)(1<<5))
581 GETFLOATSIGN(ge->Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
582 GETFLOATSIGN(ge->M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
583 GETFLOATSIGN(ge->Cuc, 16, 1.0/(double)(1<<29))
584 GETFLOAT(ge->e, 32, 1.0/(double)(1<<30)/(double)(1<<3))
585 GETFLOATSIGN(ge->Cus, 16, 1.0/(double)(1<<29))
586 GETFLOAT(ge->sqrt_A, 32, 1.0/(double)(1<<19))
587 GETBITSFACTOR(ge->TOE, 14, 60)
588 GETFLOATSIGN(ge->Cic, 16, 1.0/(double)(1<<29))
589 GETFLOATSIGN(ge->OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
590 GETFLOATSIGN(ge->Cis, 16, 1.0/(double)(1<<29))
591 GETFLOATSIGN(ge->i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
592 GETFLOATSIGN(ge->Crc, 16, 1.0/(double)(1<<5))
593 GETFLOATSIGN(ge->omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
594 GETFLOATSIGN(ge->OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
595 GETFLOATSIGN(ge->BGD_1_5A, 10, 1.0/(double)(1<<30)/(double)(1<<2))
596 if(type == 1046)
597 {
598 GETFLOATSIGN(ge->BGD_1_5B, 10, 1.0/(double)(1<<30)/(double)(1<<2))
599 GETBITS(ge->E5aHS, 2)
600 GETBITS(sv, 1)
601 ge->flags |= GALEPHF_INAV;
602 if(sv)
603 ge->flags |= GALEPHF_E5ADINVALID;
604 GETFLOATSIGN(ge->BGD_1_5B, 10, 1.0/(double)(1<<30)/(double)(1<<2))
605 }
606 else
607 {
608 ge->flags |= GALEPHF_FNAV;
609 GETBITS(ge->E5bHS, 2)
610 GETBITS(sv, 1)
611 if(sv)
612 ge->flags |= GALEPHF_E5BDINVALID;
613 }
614 ret = type;
615 }
616 break;
617 case 1020:
618 {
619 struct glonassephemeris *ge;
620 int i;
621
622 ge = &handle->ephemerisGLONASS;
623 memset(ge, 0, sizeof(*ge));
624
625 ge->flags |= GLOEPHF_PAVAILABLE;
626 GETBITS(ge->almanac_number, 6)
627 GETBITS(i, 5)
628 ge->frequency_number = i-7;
629 if(ge->almanac_number >= 1 && ge->almanac_number <= PRN_GLONASS_NUM)
630 handle->GLOFreq[ge->almanac_number-1] = 100+ge->frequency_number;
631 GETBITS(i, 1)
632 if(i)
633 ge->flags |= GLOEPHF_ALMANACHEALTHY;
634 GETBITS(i, 1)
635 if(i)
636 ge->flags |= GLOEPHF_ALMANACHEALTHOK;
637 GETBITS(i, 2)
638 if(i & 1)
639 ge->flags |= GLOEPHF_P10TRUE;
640 if(i & 2)
641 ge->flags |= GLOEPHF_P11TRUE;
642 GETBITS(i, 5)
643 ge->tk = i*60*60;
644 GETBITS(i, 6)
645 ge->tk += i*60;
646 GETBITS(i, 1)
647 ge->tk += i*30;
648 GETBITS(i, 1)
649 if(i)
650 ge->flags |= GLOEPHF_UNHEALTHY;
651 GETBITS(i, 1)
652 if(i)
653 ge->flags |= GLOEPHF_P2TRUE;
654 GETBITS(i, 7)
655 ge->tb = i*15*60;
656 GETFLOATSIGNM(ge->x_velocity, 24, 1.0/(double)(1<<20))
657 GETFLOATSIGNM(ge->x_pos, 27, 1.0/(double)(1<<11))
658 GETFLOATSIGNM(ge->x_acceleration, 5, 1.0/(double)(1<<30))
659 GETFLOATSIGNM(ge->y_velocity, 24, 1.0/(double)(1<<20))
660 GETFLOATSIGNM(ge->y_pos, 27, 1.0/(double)(1<<11))
661 GETFLOATSIGNM(ge->y_acceleration, 5, 1.0/(double)(1<<30))
662 GETFLOATSIGNM(ge->z_velocity, 24, 1.0/(double)(1<<20))
663 GETFLOATSIGNM(ge->z_pos, 27, 1.0/(double)(1<<11))
664 GETFLOATSIGNM(ge->z_acceleration, 5, 1.0/(double)(1<<30))
665 GETBITS(i, 1)
666 if(i)
667 ge->flags |= GLOEPHF_P3TRUE;
668 GETFLOATSIGNM(ge->gamma, 11, 1.0/(double)(1<<30)/(double)(1<<10))
669 SKIPBITS(3) /* GLONASS-M P, GLONASS-M ln (third string) */
670 GETFLOATSIGNM(ge->tau, 22, 1.0/(double)(1<<30)) /* GLONASS tau n(tb) */
671 SKIPBITS(5) /* GLONASS-M delta tau n(tb) */
672 GETBITS(ge->E, 5)
673 /* GETBITS(b, 1) / * GLONASS-M P4 */
674 /* GETBITS(b, 4) / * GLONASS-M Ft */
675 /* GETBITS(b, 11) / * GLONASS-M Nt */
676 /* GETBITS(b, 2) / * GLONASS-M M */
677 /* GETBITS(b, 1) / * GLONASS-M The Availability of Additional Data */
678 /* GETBITS(b, 11) / * GLONASS-M Na */
679 /* GETFLOATSIGNM(b, 32, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS tau c */
680 /* GETBITS(b, 5) / * GLONASS-M N4 */
681 /* GETFLOATSIGNM(b, 22, 1.0/(double)(1<<30)/(double)(1<<1)) / * GLONASS-M tau GPS */
682 /* GETBITS(b, 1) / * GLONASS-M ln (fifth string) */
683 ge->GPSWeek = handle->GPSWeek;
684 ge->GPSTOW = handle->GPSTOW;
685 ret = 1020;
686 }
687 break;
688 case 1001: case 1002: case 1003: case 1004:
689 if(handle->GPSWeek)
690 {
691 int lastlockl1[64];
692 int lastlockl2[64];
693 struct gnssdata *gnss;
694 int i, numsats, wasamb=0;
695
696 for(i = 0; i < 64; ++i)
697 lastlockl1[i] = lastlockl2[i] = 0;
698
699 gnss = &handle->DataNew;
700
701 SKIPBITS(12) /* id */
702 GETBITS(i,30)
703 if(i/1000 < (int)handle->GPSTOW - 86400)
704 ++handle->GPSWeek;
705 handle->GPSTOW = i/1000;
706 if(gnss->week && (gnss->timeofweek != i || gnss->week
707 != handle->GPSWeek))
708 {
709 handle->Data = *gnss;
710 memset(gnss, 0, sizeof(*gnss));
711 old = 1;
712 }
713 gnss->timeofweek = i;
714 gnss->week = handle->GPSWeek;
715
716 GETBITS(syncf,1) /* sync */
717 GETBITS(numsats,5)
718 SKIPBITS(4) /* smind, smint */
719
720 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
721 {
722 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
723 int fullsat, num;
724
725 GETBITS(sv, 6)
726 fullsat = sv < 40 ? sv : sv+80;
727 for(num = 0; num < gnss->numsats
728 && fullsat != gnss->satellites[num]; ++num)
729 ;
730
731 if(num == gnss->numsats)
732 gnss->satellites[gnss->numsats++] = fullsat;
733
734 /* L1 */
735 GETBITS(code, 1);
736 if(code)
737 {
738 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
739 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
740 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
741 gnss->codetype[num][se] =
742 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1W";
743 }
744 else
745 {
746 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
747 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
748 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
749 gnss->codetype[num][se] =
750 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1C";
751 }
752 if(!handle->info[RTCM3_MSM_GPS].type[ce])
753 {
754 handle->info[RTCM3_MSM_GPS].type[ce] =
755 handle->info[RTCM3_MSM_GPS].type[le] =
756 handle->info[RTCM3_MSM_GPS].type[se] = gnss->codetype[num][ce][1];
757 }
758 GETBITS(l1range, 24);
759 GETBITSSIGN(i, 20);
760 if((i&((1<<20)-1)) != 0x80000)
761 {
762 gnss->dataflags[num] |= (c|l);
763 gnss->measdata[num][ce] = l1range*0.02;
764 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
765 }
766 GETBITS(i, 7);
767 lastlockl1[sv] = i;
768 if(handle->lastlockGPSl1[sv] > i || i == 0)
769 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
770 if(type == 1002 || type == 1004)
771 {
772 GETBITS(amb,8);
773 if(amb && (gnss->dataflags[num] & c))
774 {
775 gnss->measdata[num][ce] += amb*299792.458;
776 gnss->measdata[num][le] += amb*299792.458;
777 ++wasamb;
778 }
779 GETBITS(i, 8);
780 if(i)
781 {
782 gnss->dataflags[num] |= s;
783 gnss->measdata[num][se] = i*0.25;
784 i /= 4*4;
785 if(i > 9) i = 9;
786 else if(i < 1) i = 1;
787 gnss->snrL1[num] = i;
788 }
789 }
790 gnss->measdata[num][le] /= GPS_WAVELENGTH_L1;
791 if(type == 1003 || type == 1004)
792 {
793 /* L2 */
794 GETBITS(code,2);
795 if(code)
796 {
797 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
798 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
799 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
800 if(code >= 2)
801 {
802 gnss->codetype[num][se] =
803 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2W";
804 gnss->dataflags2[num] |= GNSSDF2_XCORRL2;
805 }
806 else
807 {
808 gnss->codetype[num][se] =
809 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2P";
810 }
811 }
812 else
813 {
814 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
815 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
816 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
817 gnss->codetype[num][se] =
818 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2 ";
819 }
820 if(!handle->info[RTCM3_MSM_GPS].type[ce])
821 {
822 handle->info[RTCM3_MSM_GPS].type[ce] =
823 handle->info[RTCM3_MSM_GPS].type[le] =
824 handle->info[RTCM3_MSM_GPS].type[se] = gnss->codetype[num][ce][1];
825 }
826 GETBITSSIGN(i,14);
827 if((i&((1<<14)-1)) != 0x2000)
828 {
829 gnss->dataflags[num] |= c;
830 gnss->measdata[num][ce] = l1range*0.02+i*0.02
831 +amb*299792.458;
832 }
833 GETBITSSIGN(i,20);
834 if((i&((1<<20)-1)) != 0x80000)
835 {
836 gnss->dataflags[num] |= l;
837 gnss->measdata[num][le] = l1range*0.02+i*0.0005
838 +amb*299792.458;
839 }
840 GETBITS(i,7);
841 lastlockl2[sv] = i;
842 if(handle->lastlockGPSl2[sv] > i || i == 0)
843 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
844 if(type == 1004)
845 {
846 GETBITS(i, 8);
847 if(i)
848 {
849 gnss->dataflags[num] |= s;
850 gnss->measdata[num][se] = i*0.25;
851 i /= 4*4;
852 if(i > 9) i = 9;
853 else if(i < 1) i = 1;
854 gnss->snrL2[num] = i;
855 }
856 }
857 gnss->measdata[num][le] /= GPS_WAVELENGTH_L2;
858 }
859 }
860 for(i = 0; i < 64; ++i)
861 {
862 handle->lastlockGPSl1[i] = lastlockl1[i];
863 handle->lastlockGPSl2[i] = lastlockl2[i];
864 }
865 if(!syncf && !old)
866 {
867 handle->Data = *gnss;
868 memset(gnss, 0, sizeof(*gnss));
869 }
870 if(!syncf || old)
871 {
872 if(wasamb) /* not RINEX compatible without */
873 ret = 1;
874 else
875 ret = 2;
876 }
877#ifdef NO_RTCM3_MAIN
878 else
879 ret = type;
880#endif /* NO_RTCM3_MAIN */
881 }
882 break;
883 case 1009: case 1010: case 1011: case 1012:
884 {
885 int lastlockl1[64];
886 int lastlockl2[64];
887 struct gnssdata *gnss;
888 int i, numsats;
889 int wasamb=0;
890
891 for(i = 0; i < 64; ++i)
892 lastlockl1[i] = lastlockl2[i] = 0;
893
894 gnss = &handle->DataNew;
895
896 SKIPBITS(12) /* id */;
897 GETBITS(i,27) /* tk */
898
899 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
900 i = handle->GPSTOW*1000;
901 if(gnss->week && (gnss->timeofweek != i || gnss->week
902 != handle->GPSWeek))
903 {
904 handle->Data = *gnss;
905 memset(gnss, 0, sizeof(*gnss));
906 old = 1;
907 }
908
909 gnss->timeofweek = i;
910 gnss->week = handle->GPSWeek;
911
912 GETBITS(syncf,1) /* sync */
913 GETBITS(numsats,5)
914
915 SKIPBITS(4) /* smind, smint */
916
917 while(numsats-- && gnss->numsats < GNSS_MAXSATS)
918 {
919 int sv, code, l1range, c,l,s,ce,le,se,amb=0;
920 int freq;
921 int fullsat, num;
922
923 GETBITS(sv, 6)
924 fullsat = sv-1 + PRN_GLONASS_START;
925 for(num = 0; num < gnss->numsats
926 && fullsat != gnss->satellites[num]; ++num)
927 ;
928
929 if(num == gnss->numsats)
930 gnss->satellites[gnss->numsats++] = fullsat;
931
932 /* L1 */
933 GETBITS(code, 1)
934 GETBITS(freq, 5)
935
936 if(sv >= 1 && sv <= PRN_GLONASS_NUM)
937 handle->GLOFreq[sv-1] = 100+freq-7;
938
939 if(code)
940 {
941 c = GNSSDF_P1DATA; ce = GNSSENTRY_P1DATA;
942 l = GNSSDF_L1PDATA; le = GNSSENTRY_L1PDATA;
943 s = GNSSDF_S1PDATA; se = GNSSENTRY_S1PDATA;
944 gnss->codetype[num][se] =
945 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1P";
946 }
947 else
948 {
949 c = GNSSDF_C1DATA; ce = GNSSENTRY_C1DATA;
950 l = GNSSDF_L1CDATA; le = GNSSENTRY_L1CDATA;
951 s = GNSSDF_S1CDATA; se = GNSSENTRY_S1CDATA;
952 gnss->codetype[num][se] =
953 gnss->codetype[num][ce] = gnss->codetype[num][le] = "1C";
954 }
955 if(!handle->info[RTCM3_MSM_GLONASS].type[ce])
956 {
957 handle->info[RTCM3_MSM_GLONASS].type[ce] =
958 handle->info[RTCM3_MSM_GLONASS].type[le] =
959 handle->info[RTCM3_MSM_GLONASS].type[se] = gnss->codetype[num][ce][1];
960 }
961 GETBITS(l1range, 25)
962 GETBITSSIGN(i, 20)
963 if((i&((1<<20)-1)) != 0x80000)
964 {
965 /* Handle this like GPS. Actually for GLONASS L1 range is always
966 valid. To be on the save side, we handle it as invalid like we
967 do for GPS and also remove range in case of 0x80000. */
968 gnss->dataflags[num] |= (c|l);
969 gnss->measdata[num][ce] = l1range*0.02;
970 gnss->measdata[num][le] = l1range*0.02+i*0.0005;
971 }
972 GETBITS(i, 7)
973 lastlockl1[sv] = i;
974 if(handle->lastlockGLOl1[sv] > i || i == 0)
975 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL1;
976 if(type == 1010 || type == 1012)
977 {
978 GETBITS(amb,7)
979 if(amb && (gnss->dataflags[num] & c))
980 {
981 gnss->measdata[num][ce] += amb*599584.916;
982 gnss->measdata[num][le] += amb*599584.916;
983 ++wasamb;
984 }
985 GETBITS(i, 8)
986 if(i)
987 {
988 gnss->dataflags[num] |= s;
989 gnss->measdata[num][se] = i*0.25;
990 i /= 4*4;
991 if(i > 9) i = 9;
992 else if(i < 1) i = 1;
993 gnss->snrL1[num] = i;
994 }
995 }
996 gnss->measdata[num][le] /= GLO_WAVELENGTH_L1(freq-7);
997 if(type == 1011 || type == 1012)
998 {
999 /* L2 */
1000 GETBITS(code,2)
1001 if(code)
1002 {
1003 c = GNSSDF_P2DATA; ce = GNSSENTRY_P2DATA;
1004 l = GNSSDF_L2PDATA; le = GNSSENTRY_L2PDATA;
1005 s = GNSSDF_S2PDATA; se = GNSSENTRY_S2PDATA;
1006 gnss->codetype[num][se] =
1007 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2P";
1008 }
1009 else
1010 {
1011 c = GNSSDF_C2DATA; ce = GNSSENTRY_C2DATA;
1012 l = GNSSDF_L2CDATA; le = GNSSENTRY_L2CDATA;
1013 s = GNSSDF_S2CDATA; se = GNSSENTRY_S2CDATA;
1014 gnss->codetype[num][se] =
1015 gnss->codetype[num][ce] = gnss->codetype[num][le] = "2C";
1016 }
1017 if(!handle->info[RTCM3_MSM_GLONASS].type[ce])
1018 {
1019 handle->info[RTCM3_MSM_GLONASS].type[ce] =
1020 handle->info[RTCM3_MSM_GLONASS].type[le] =
1021 handle->info[RTCM3_MSM_GLONASS].type[se] = gnss->codetype[num][ce][1];
1022 }
1023 GETBITSSIGN(i,14)
1024 if((i&((1<<14)-1)) != 0x2000)
1025 {
1026 gnss->dataflags[num] |= c;
1027 gnss->measdata[num][ce] = l1range*0.02+i*0.02
1028 +amb*599584.916;
1029 }
1030 GETBITSSIGN(i,20)
1031 if((i&((1<<20)-1)) != 0x80000)
1032 {
1033 gnss->dataflags[num] |= l;
1034 gnss->measdata[num][le] = l1range*0.02+i*0.0005
1035 +amb*599584.916;
1036 }
1037 GETBITS(i,7)
1038 lastlockl2[sv] = i;
1039 if(handle->lastlockGLOl2[sv] > i || i == 0)
1040 gnss->dataflags2[num] |= GNSSDF2_LOCKLOSSL2;
1041 if(type == 1012)
1042 {
1043 GETBITS(i, 8)
1044 if(i)
1045 {
1046 gnss->dataflags[num] |= s;
1047 gnss->measdata[num][se] = i*0.25;
1048 i /= 4*4;
1049 if(i > 9) i = 9;
1050 else if(i < 1) i = 1;
1051 gnss->snrL2[num] = i;
1052 }
1053 }
1054 gnss->measdata[num][le] /= GLO_WAVELENGTH_L2(freq-7);
1055 }
1056 if(!sv || sv > 24) /* illegal, remove it again */
1057 --gnss->numsats;
1058 }
1059 for(i = 0; i < 64; ++i)
1060 {
1061 handle->lastlockGLOl1[i] = lastlockl1[i];
1062 handle->lastlockGLOl2[i] = lastlockl2[i];
1063 }
1064 if(!syncf && !old)
1065 {
1066 handle->Data = *gnss;
1067 memset(gnss, 0, sizeof(*gnss));
1068 }
1069 if(!syncf || old)
1070 {
1071 if(wasamb) /* not RINEX compatible without */
1072 ret = 1;
1073 else
1074 ret = 2;
1075 }
1076#ifdef NO_RTCM3_MAIN
1077 else
1078 ret = type;
1079#endif /* NO_RTCM3_MAIN */
1080 }
1081 break;
1082 case 1071: case 1081: case 1091: case 1101: case 1111: case 1121:
1083 case 1072: case 1082: case 1092: case 1102: case 1112: case 1122:
1084 case 1073: case 1083: case 1093: case 1103: case 1113: case 1123:
1085 case 1074: case 1084: case 1094: case 1104: case 1114: case 1124:
1086 case 1075: case 1085: case 1095: case 1105: case 1115: case 1125:
1087 case 1076: case 1086: case 1096: case 1106: case 1116: case 1126:
1088 case 1077: case 1087: case 1097: case 1107: case 1117: case 1127:
1089 if(handle->GPSWeek)
1090 {
1091 struct CodeData {
1092 int typeR;
1093 int typeP;
1094 int typeD;
1095 int typeS;
1096 int lock;
1097 double wl;
1098 const char *code; /* currently unused */
1099 };
1100 struct CodeData gps[RTCM3_MSM_NUMSIG] =
1101 {
1102 {0,0,0,0,0,0,0},
1103 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1104 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
1105 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1106 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
1107 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1108 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1W"},
1109 {0,0,0,0,0,0,0}/*{GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1110 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1Y"}*/,
1111 {0,0,0,0,0,0,0},
1112 {0,0,0,0,0,0,0},
1113 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1114 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2C"},
1115 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1116 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2P"},
1117 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1118 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2W"},
1119 {0,0,0,0,0,0,0}/*{GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1120 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2Y"}*/,
1121 {0,0,0,0,0,0,0},
1122 {0,0,0,0,0,0,0},
1123 {0,0,0,0,0,0,0},
1124 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1125 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
1126 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1127 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
1128 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1129 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
1130 {0,0,0,0,0,0,0},
1131 {0,0,0,0,0,0,0},
1132 {0,0,0,0,0,0,0},
1133 {0,0,0,0,0,0,0},
1134 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1135 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
1136 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1137 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
1138 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1139 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"},
1140 {0,0,0,0,0,0,0},
1141 {0,0,0,0,0,0,0},
1142 {0,0,0,0,0,0,0},
1143 {0,0,0,0,0,0,0},
1144 {0,0,0,0,0,0,0},
1145 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1146 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1S"},
1147 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1148 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1L"},
1149 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1150 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1X"}
1151 };
1152 /* NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later! */
1153 struct CodeData glo[RTCM3_MSM_NUMSIG] =
1154 {
1155 {0,0,0,0,0,0,0},
1156 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1157 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,0.0,"1C"},
1158 {GNSSENTRY_P1DATA,GNSSENTRY_L1PDATA,GNSSENTRY_D1PDATA,
1159 GNSSENTRY_S1PDATA,GNSSDF2_LOCKLOSSL1,0.0,"1P"},
1160 {0,0,0,0,0,0,0},
1161 {0,0,0,0,0,0,0},
1162 {0,0,0,0,0,0,0},
1163 {0,0,0,0,0,0,0},
1164 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1165 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,1.0,"2C"},
1166 {GNSSENTRY_P2DATA,GNSSENTRY_L2PDATA,GNSSENTRY_D2PDATA,
1167 GNSSENTRY_S2PDATA,GNSSDF2_LOCKLOSSL2,1.0,"2P"},
1168 {0,0,0,0,0,0,0},
1169 {0,0,0,0,0,0,0},
1170 {0,0,0,0,0,0,0},
1171 {0,0,0,0,0,0,0},
1172 {0,0,0,0,0,0,0},
1173 {0,0,0,0,0,0,0},
1174 {0,0,0,0,0,0,0},
1175 {0,0,0,0,0,0,0},
1176 {0,0,0,0,0,0,0},
1177 {0,0,0,0,0,0,0},
1178 {0,0,0,0,0,0,0},
1179 {0,0,0,0,0,0,0},
1180 {0,0,0,0,0,0,0},
1181 {0,0,0,0,0,0,0},
1182 {0,0,0,0,0,0,0},
1183 {0,0,0,0,0,0,0},
1184 {0,0,0,0,0,0,0},
1185 {0,0,0,0,0,0,0},
1186 {0,0,0,0,0,0,0},
1187 {0,0,0,0,0,0,0},
1188 {0,0,0,0,0,0,0},
1189 {0,0,0,0,0,0,0},
1190 {0,0,0,0,0,0,0}
1191 };
1192 struct CodeData gal[RTCM3_MSM_NUMSIG] =
1193 {
1194 {0,0,0,0,0,0,0},
1195 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1196 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1C"},
1197 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1198 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1A"},
1199 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1200 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1B"},
1201 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1202 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1X"},
1203 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1204 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GAL_WAVELENGTH_E1,"1Z"},
1205 {0,0,0,0,0,0,0},
1206 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1207 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6C"},
1208 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1209 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6A"},
1210 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1211 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6B"},
1212 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1213 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6X"},
1214 {GNSSENTRY_C6DATA,GNSSENTRY_L6DATA,GNSSENTRY_D6DATA,
1215 GNSSENTRY_S6DATA,GNSSDF2_LOCKLOSSE6,GAL_WAVELENGTH_E6,"6Z"},
1216 {0,0,0,0,0,0,0},
1217 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1218 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7I"},
1219 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1220 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7Q"},
1221 {GNSSENTRY_C5BDATA,GNSSENTRY_L5BDATA,GNSSENTRY_D5BDATA,
1222 GNSSENTRY_S5BDATA,GNSSDF2_LOCKLOSSE5B,GAL_WAVELENGTH_E5B,"7X"},
1223 {0,0,0,0,0,0,0},
1224 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1225 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8I"},
1226 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1227 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8Q"},
1228 {GNSSENTRY_C5ABDATA,GNSSENTRY_L5ABDATA,GNSSENTRY_D5ABDATA,
1229 GNSSENTRY_S5ABDATA,GNSSDF2_LOCKLOSSE5AB,GAL_WAVELENGTH_E5AB,"8X"},
1230 {0,0,0,0,0,0,0},
1231 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1232 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5I"},
1233 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1234 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5Q"},
1235 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1236 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GAL_WAVELENGTH_E5A,"5X"},
1237 {0,0,0,0,0,0,0},
1238 {0,0,0,0,0,0,0},
1239 {0,0,0,0,0,0,0},
1240 {0,0,0,0,0,0,0},
1241 {0,0,0,0,0,0,0},
1242 {0,0,0,0,0,0,0},
1243 {0,0,0,0,0,0,0},
1244 {0,0,0,0,0,0,0},
1245 };
1246 struct CodeData qzss[RTCM3_MSM_NUMSIG] =
1247 {
1248 {0,0,0,0,0,0,0},
1249 {GNSSENTRY_C1DATA,GNSSENTRY_L1CDATA,GNSSENTRY_D1CDATA,
1250 GNSSENTRY_S1CDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1C"},
1251 {0,0,0,0,0,0,0},
1252 {0,0,0,0,0,0,0},
1253 {0,0,0,0,0,0,0},
1254 {GNSSENTRY_CSAIFDATA,GNSSENTRY_LSAIFDATA,GNSSENTRY_DSAIFDATA,
1255 GNSSENTRY_SSAIFDATA,GNSSDF2_LOCKLOSSSAIF,GPS_WAVELENGTH_L1,"1Z"},
1256 {0,0,0,0,0,0,0},
1257 {0,0,0,0,0,0,0},
1258 {GNSSENTRY_CLEXDATA,GNSSENTRY_LLEXDATA,GNSSENTRY_DLEXDATA,
1259 GNSSENTRY_SLEXDATA,GNSSDF2_LOCKLOSSLEX,QZSS_WAVELENGTH_LEX,"6S"},
1260 {GNSSENTRY_CLEXDATA,GNSSENTRY_LLEXDATA,GNSSENTRY_DLEXDATA,
1261 GNSSENTRY_SLEXDATA,GNSSDF2_LOCKLOSSLEX,QZSS_WAVELENGTH_LEX,"6L"},
1262 {GNSSENTRY_CLEXDATA,GNSSENTRY_LLEXDATA,GNSSENTRY_DLEXDATA,
1263 GNSSENTRY_SLEXDATA,GNSSDF2_LOCKLOSSLEX,QZSS_WAVELENGTH_LEX,"6X"},
1264 {0,0,0,0,0,0,0},
1265 {0,0,0,0,0,0,0},
1266 {0,0,0,0,0,0,0},
1267 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1268 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2S"},
1269 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1270 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2L"},
1271 {GNSSENTRY_C2DATA,GNSSENTRY_L2CDATA,GNSSENTRY_D2CDATA,
1272 GNSSENTRY_S2CDATA,GNSSDF2_LOCKLOSSL2,GPS_WAVELENGTH_L2,"2X"},
1273 {0,0,0,0,0,0,0},
1274 {0,0,0,0,0,0,0},
1275 {0,0,0,0,0,0,0},
1276 {0,0,0,0,0,0,0},
1277 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1278 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5I"},
1279 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1280 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5Q"},
1281 {GNSSENTRY_C5DATA,GNSSENTRY_L5DATA,GNSSENTRY_D5DATA,
1282 GNSSENTRY_S5DATA,GNSSDF2_LOCKLOSSL5,GPS_WAVELENGTH_L5,"5X"},
1283 {0,0,0,0,0,0,0},
1284 {0,0,0,0,0,0,0},
1285 {0,0,0,0,0,0,0},
1286 {0,0,0,0,0,0,0},
1287 {0,0,0,0,0,0,0},
1288 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1289 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1D"},
1290 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1291 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1P"},
1292 {GNSSENTRY_C1NDATA,GNSSENTRY_L1NDATA,GNSSENTRY_D1NDATA,
1293 GNSSENTRY_S1NDATA,GNSSDF2_LOCKLOSSL1,GPS_WAVELENGTH_L1,"1X"}
1294 };
1295 struct CodeData compass[RTCM3_MSM_NUMSIG] =
1296 {
1297 {0,0,0,0,0,0,0},
1298 {GNSSENTRY_CB1DATA,GNSSENTRY_LB1DATA,GNSSENTRY_DB1DATA,
1299 GNSSENTRY_SB1DATA,GNSSDF2_LOCKLOSSB1,COMPASS_WAVELENGTH_B1,"1I"},
1300 {0,0,0,0,0,0,0},
1301 {0,0,0,0,0,0,0},
1302 {0,0,0,0,0,0,0},
1303 {0,0,0,0,0,0,0},
1304 {0,0,0,0,0,0,0},
1305 {GNSSENTRY_CB3DATA,GNSSENTRY_LB3DATA,GNSSENTRY_DB3DATA,
1306 GNSSENTRY_SB3DATA,GNSSDF2_LOCKLOSSB3,COMPASS_WAVELENGTH_B3,"6I"},
1307 {0,0,0,0,0,0,0},
1308 {0,0,0,0,0,0,0},
1309 {0,0,0,0,0,0,0},
1310 {0,0,0,0,0,0,0},
1311 {0,0,0,0,0,0,0},
1312 {GNSSENTRY_CB2DATA,GNSSENTRY_LB2DATA,GNSSENTRY_DB2DATA,
1313 GNSSENTRY_SB2DATA,GNSSDF2_LOCKLOSSB2,COMPASS_WAVELENGTH_B2,"7I"},
1314 {0,0,0,0,0,0,0},
1315 {0,0,0,0,0,0,0},
1316 {0,0,0,0,0,0,0},
1317 {0,0,0,0,0,0,0},
1318 {0,0,0,0,0,0,0},
1319 {0,0,0,0,0,0,0},
1320 {0,0,0,0,0,0,0},
1321 {0,0,0,0,0,0,0},
1322 {0,0,0,0,0,0,0},
1323 {0,0,0,0,0,0,0},
1324 {0,0,0,0,0,0,0},
1325 {0,0,0,0,0,0,0},
1326 {0,0,0,0,0,0,0},
1327 {0,0,0,0,0,0,0},
1328 {0,0,0,0,0,0,0},
1329 {0,0,0,0,0,0,0},
1330 {0,0,0,0,0,0,0},
1331 {0,0,0,0,0,0,0},
1332 };
1333
1334 int sys = RTCM3_MSM_GPS, i=0, count, j, old = 0, wasnoamb = 0,
1335 start=PRN_GPS_START;
1336 int syncf, sigmask, numsat = 0, numsig = 0, numcells;
1337 uint64_t satmask, cellmask, ui;
1338 double rrmod[RTCM3_MSM_NUMSAT];
1339 int rrint[RTCM3_MSM_NUMSAT], rdop[RTCM3_MSM_NUMSAT],
1340 extsat[RTCM3_MSM_NUMSAT];
1341 int ll[RTCM3_MSM_NUMCELLS]/*, hc[RTCM3_MSM_NUMCELLS]*/;
1342 double cnr[RTCM3_MSM_NUMCELLS];
1343 double cp[RTCM3_MSM_NUMCELLS], psr[RTCM3_MSM_NUMCELLS],
1344 dop[RTCM3_MSM_NUMCELLS];
1345 struct gnssdata *gnss = &handle->DataNew;
1346
1347 SKIPBITS(12)
1348 if(type >= 1121)
1349 {
1350 sys = RTCM3_MSM_COMPASS;
1351 start = PRN_COMPASS_START;
1352 }
1353 else if(type >= 1111)
1354 {
1355 sys = RTCM3_MSM_QZSS;
1356 start = PRN_QZSS_START;
1357 }
1358 else if(type >= 1101)
1359 {
1360 sys = RTCM3_MSM_SBAS;
1361 start = PRN_SBAS_START;
1362 }
1363 else if(type >= 1091)
1364 {
1365 sys = RTCM3_MSM_GALILEO;
1366 start = PRN_GALILEO_START;
1367 }
1368 else if(type >= 1081)
1369 {
1370 sys = RTCM3_MSM_GLONASS;
1371 start = PRN_GLONASS_START;
1372 }
1373
1374 for(i = 0; i < RTCM3_MSM_NUMSAT; ++i)
1375 extsat[i] = 15;
1376
1377 switch(sys)
1378 {
1379 case RTCM3_MSM_COMPASS:
1380 GETBITS(i,30)
1381 i += 14000;
1382 if(i >= 7*24*60*60*1000)
1383 i -= 7*24*60*60*1000;
1384 if(i/1000 < (int)handle->GPSTOW - 86400)
1385 ++handle->GPSWeek;
1386 handle->GPSTOW = i/1000;
1387 break;
1388 case RTCM3_MSM_GALILEO: /* use DF004 instead of DF248 */
1389 case RTCM3_MSM_QZSS:
1390 case RTCM3_MSM_SBAS:
1391 case RTCM3_MSM_GPS:
1392 GETBITS(i,30)
1393 if(i/1000 < (int)handle->GPSTOW - 86400)
1394 ++handle->GPSWeek;
1395 handle->GPSTOW = i/1000;
1396 break;
1397 case RTCM3_MSM_GLONASS:
1398 SKIPBITS(3)
1399 GETBITS(i,27) /* tk */
1400
1401 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
1402 i = handle->GPSTOW*1000;
1403 break;
1404 }
1405
1406 if(gnss->week && (gnss->timeofweek != i || gnss->week
1407 != handle->GPSWeek))
1408 {
1409 handle->Data = *gnss;
1410 memset(gnss, 0, sizeof(*gnss));
1411 old = 1;
1412 }
1413 gnss->timeofweek = i;
1414 gnss->week = handle->GPSWeek;
1415
1416 GETBITS(syncf, 1)
1417 SKIPBITS(3+7+2+2+1+3)
1418 GETBITS64(satmask, RTCM3_MSM_NUMSAT)
1419
1420 /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
1421 for(ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
1422 ++numsat;
1423 GETBITS(sigmask, RTCM3_MSM_NUMSIG)
1424 for(i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
1425 ++numsig;
1426 i = numsat*numsig;
1427 GETBITS64(cellmask, (unsigned)i)
1428
1429 switch(type % 10)
1430 {
1431 case 1: case 2: case 3:
1432 ++wasnoamb;
1433 for(j = numsat; j--;)
1434 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1435 break;
1436 case 4: case 6:
1437 for(j = numsat; j--;)
1438 GETBITS(rrint[j], 8)
1439 for(j = numsat; j--;)
1440 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1441 break;
1442 case 5: case 7:
1443 for(j = numsat; j--;)
1444 GETBITS(rrint[j], 8)
1445 for(j = numsat; j--;)
1446 GETBITS(extsat[j], 4)
1447 for(j = numsat; j--;)
1448 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1449 for(j = numsat; j--;)
1450 GETBITSSIGN(rdop[j], 14)
1451 break;
1452 }
1453
1454 numcells = numsat*numsig;
1455 if(numcells <= RTCM3_MSM_NUMCELLS)
1456 {
1457 switch(type % 10)
1458 {
1459 case 1:
1460 for(count = numcells; count--;)
1461 if(cellmask & (UINT64(1)<<count))
1462 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1463 break;
1464 case 2:
1465 for(count = numcells; count--;)
1466 if(cellmask & (UINT64(1)<<count))
1467 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1468 for(count = numcells; count--;)
1469 if(cellmask & (UINT64(1)<<count))
1470 GETBITS(ll[count], 4)
1471 for(count = numcells; count--;)
1472 if(cellmask & (UINT64(1)<<count))
1473 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1474 break;
1475 case 3:
1476 for(count = numcells; count--;)
1477 if(cellmask & (UINT64(1)<<count))
1478 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1479 for(count = numcells; count--;)
1480 if(cellmask & (UINT64(1)<<count))
1481 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1482 for(count = numcells; count--;)
1483 if(cellmask & (UINT64(1)<<count))
1484 GETBITS(ll[count], 4)
1485 for(count = numcells; count--;)
1486 if(cellmask & (UINT64(1)<<count))
1487 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1488 break;
1489 case 4:
1490 for(count = numcells; count--;)
1491 if(cellmask & (UINT64(1)<<count))
1492 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1493 for(count = numcells; count--;)
1494 if(cellmask & (UINT64(1)<<count))
1495 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1496 for(count = numcells; count--;)
1497 if(cellmask & (UINT64(1)<<count))
1498 GETBITS(ll[count], 4)
1499 for(count = numcells; count--;)
1500 if(cellmask & (UINT64(1)<<count))
1501 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1502 for(count = numcells; count--;)
1503 if(cellmask & (UINT64(1)<<count))
1504 GETBITS(cnr[count], 6)
1505 break;
1506 case 5:
1507 for(count = numcells; count--;)
1508 if(cellmask & (UINT64(1)<<count))
1509 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1510 for(count = numcells; count--;)
1511 if(cellmask & (UINT64(1)<<count))
1512 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1513 for(count = numcells; count--;)
1514 if(cellmask & (UINT64(1)<<count))
1515 GETBITS(ll[count], 4)
1516 for(count = numcells; count--;)
1517 if(cellmask & (UINT64(1)<<count))
1518 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1519 for(count = numcells; count--;)
1520 if(cellmask & (UINT64(1)<<count))
1521 GETFLOAT(cnr[count], 6, 1.0)
1522 for(count = numcells; count--;)
1523 if(cellmask & (UINT64(1)<<count))
1524 GETFLOATSIGN(dop[count], 15, 0.0001)
1525 break;
1526 case 6:
1527 for(count = numcells; count--;)
1528 if(cellmask & (UINT64(1)<<count))
1529 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1530 for(count = numcells; count--;)
1531 if(cellmask & (UINT64(1)<<count))
1532 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1533 for(count = numcells; count--;)
1534 if(cellmask & (UINT64(1)<<count))
1535 GETBITS(ll[count], 10)
1536 for(count = numcells; count--;)
1537 if(cellmask & (UINT64(1)<<count))
1538 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1539 for(count = numcells; count--;)
1540 if(cellmask & (UINT64(1)<<count))
1541 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1542 break;
1543 case 7:
1544 for(count = numcells; count--;)
1545 if(cellmask & (UINT64(1)<<count))
1546 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1547 for(count = numcells; count--;)
1548 if(cellmask & (UINT64(1)<<count))
1549 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1550 for(count = numcells; count--;)
1551 if(cellmask & (UINT64(1)<<count))
1552 GETBITS(ll[count], 10)
1553 for(count = numcells; count--;)
1554 if(cellmask & (UINT64(1)<<count))
1555 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
1556 for(count = numcells; count--;)
1557 if(cellmask & (UINT64(1)<<count))
1558 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1559 for(count = numcells; count--;)
1560 if(cellmask & (UINT64(1)<<count))
1561 GETFLOATSIGN(dop[count], 15, 0.0001)
1562 break;
1563 }
1564 i = RTCM3_MSM_NUMSAT;
1565 j = -1;
1566 for(count = numcells; count--;)
1567 {
1568 while(j >= 0 && !(sigmask&(1<<--j)))
1569 ;
1570 if(j < 0)
1571 {
1572 while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1573 ;
1574 j = RTCM3_MSM_NUMSIG;
1575 while(!(sigmask&(1<<--j)))
1576 ;
1577 --numsat;
1578 }
1579 if(cellmask & (UINT64(1)<<count))
1580 {
1581 struct CodeData cd = {0,0,0,0,0,0,0};
1582 double wl = 0.0;
1583 switch(sys)
1584 {
1585 case RTCM3_MSM_QZSS:
1586 cd = qzss[RTCM3_MSM_NUMSIG-j-1];
1587 wl = cd.wl;
1588 break;
1589 case RTCM3_MSM_COMPASS:
1590 cd = compass[RTCM3_MSM_NUMSIG-j-1];
1591 wl = cd.wl;
1592 break;
1593 case RTCM3_MSM_GPS: case RTCM3_MSM_SBAS:
1594 cd = gps[RTCM3_MSM_NUMSIG-j-1];
1595 wl = cd.wl;
1596 break;
1597 case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1598 {
1599 int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1600 if(!k && extsat[numsat] < 14)
1601 {
1602 k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1]
1603 = 100+extsat[numsat]-7;
1604 }
1605 if(k)
1606 {
1607 if(cd.wl == 0.0)
1608 wl = GLO_WAVELENGTH_L1(k-100);
1609 else if(cd.wl == 1.0)
1610 wl = GLO_WAVELENGTH_L2(k-100);
1611 }
1612 }
1613 break;
1614 case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1615 wl = cd.wl;
1616 break;
1617 }
1618 if(cd.lock && wl) /* lock cannot have a valid zero value */
1619 {
1620 int fullsat = RTCM3_MSM_NUMSAT-i-1, num;
1621
1622 if(sys == RTCM3_MSM_GALILEO && fullsat >= 50 && fullsat <= 51)
1623 fullsat += PRN_GIOVE_START-50;
1624 else
1625 fullsat += start;
1626
1627 for(num = 0; num < gnss->numsats
1628 && fullsat != gnss->satellites[num]; ++num)
1629 ;
1630
1631 if(num == gnss->numsats)
1632 gnss->satellites[gnss->numsats++] = fullsat;
1633
1634 gnss->codetype[num][cd.typeR] =
1635 gnss->codetype[num][cd.typeP] =
1636 gnss->codetype[num][cd.typeD] =
1637 gnss->codetype[num][cd.typeS] = cd.code;
1638 if(!handle->info[sys].type[cd.typeR])
1639 {
1640 handle->info[sys].type[cd.typeR] =
1641 handle->info[sys].type[cd.typeP] =
1642 handle->info[sys].type[cd.typeD] =
1643 handle->info[sys].type[cd.typeS] = cd.code[1];
1644 }
1645
1646 switch(type % 10)
1647 {
1648 case 1:
1649 if(psr[count] > -1.0/(1<<10))
1650 {
1651 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1652 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1653 gnss->dataflags[num] |= (1LL<<cd.typeR);
1654 }
1655 break;
1656 case 2:
1657 if(wl && cp[count] > -1.0/(1<<8))
1658 {
1659 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1660 +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1661 if(handle->lastlockmsm[j][i] > ll[count])
1662 gnss->dataflags2[num] |= cd.lock;
1663 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1664 gnss->dataflags[num] |= (1LL<<cd.typeP);
1665 }
1666 break;
1667 case 3:
1668 if(psr[count] > -1.0/(1<<10))
1669 {
1670 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1671 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1672 gnss->dataflags[num] |= (1LL<<cd.typeR);
1673 }
1674
1675 if(wl && cp[count] > -1.0/(1<<8))
1676 {
1677 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1678 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1679 if(handle->lastlockmsm[j][i] > ll[count])
1680 gnss->dataflags2[num] |= cd.lock;
1681 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1682 gnss->dataflags[num] |= (1LL<<cd.typeP);
1683 }
1684 break;
1685 case 4:
1686 if(psr[count] > -1.0/(1<<10))
1687 {
1688 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1689 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1690 gnss->dataflags[num] |= (1LL<<cd.typeR);
1691 }
1692
1693 if(wl && cp[count] > -1.0/(1<<8))
1694 {
1695 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1696 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1697 if(handle->lastlockmsm[j][i] > ll[count])
1698 gnss->dataflags2[num] |= cd.lock;
1699 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1700 gnss->dataflags[num] |= (1LL<<cd.typeP);
1701 }
1702
1703 gnss->measdata[num][cd.typeS] = cnr[count];
1704 gnss->dataflags[num] |= (1LL<<cd.typeS);
1705 break;
1706 case 5:
1707 if(psr[count] > -1.0/(1<<10))
1708 {
1709 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1710 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1711 gnss->dataflags[num] |= (1LL<<cd.typeR);
1712 }
1713
1714 if(wl && cp[count] > -1.0/(1<<8))
1715 {
1716 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1717 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1718 if(handle->lastlockmsm[j][i] > ll[count])
1719 gnss->dataflags2[num] |= cd.lock;
1720 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1721 gnss->dataflags[num] |= (1LL<<cd.typeP);
1722 }
1723
1724 gnss->measdata[num][cd.typeS] = cnr[count];
1725 gnss->dataflags[num] |= (1<<cd.typeS);
1726
1727 if(dop[count] > -1.6384)
1728 {
1729 gnss->measdata[num][cd.typeD] = -(dop[count]
1730 +rdop[numsat])/wl;
1731 gnss->dataflags[num] |= (1LL<<cd.typeD);
1732 }
1733 break;
1734 case 6:
1735 if(psr[count] > -1.0/(1<<10))
1736 {
1737 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1738 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1739 gnss->dataflags[num] |= (1LL<<cd.typeR);
1740 }
1741
1742 if(wl && cp[count] > -1.0/(1<<8))
1743 {
1744 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1745 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1746 if(handle->lastlockmsm[j][i] > ll[count])
1747 gnss->dataflags2[num] |= cd.lock;
1748 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1749 gnss->dataflags[num] |= (1LL<<cd.typeP);
1750 }
1751
1752 gnss->measdata[num][cd.typeS] = cnr[count];
1753 gnss->dataflags[num] |= (1LL<<cd.typeS);
1754 break;
1755 case 7:
1756 if(psr[count] > -1.0/(1<<10))
1757 {
1758 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1759 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1760 gnss->dataflags[num] |= (1LL<<cd.typeR);
1761 }
1762
1763 if(wl && cp[count] > -1.0/(1<<8))
1764 {
1765 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1766 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1767 if(handle->lastlockmsm[j][i] > ll[count])
1768 gnss->dataflags2[num] |= cd.lock;
1769 handle->lastlockmsm[j][i] = ll[count] > 255 ? 255 : ll[count];
1770 gnss->dataflags[num] |= (1LL<<cd.typeP);
1771 }
1772
1773 gnss->measdata[num][cd.typeS] = cnr[count];
1774 gnss->dataflags[num] |= (1LL<<cd.typeS);
1775
1776 if(dop[count] > -1.6384)
1777 {
1778 gnss->measdata[num][cd.typeD] = -(dop[count]
1779 +rdop[numsat])/wl;
1780 gnss->dataflags[num] |= (1LL<<cd.typeD);
1781 }
1782 break;
1783 }
1784 }
1785 }
1786 }
1787 }
1788 if(!syncf && !old)
1789 {
1790 handle->Data = *gnss;
1791 memset(gnss, 0, sizeof(*gnss));
1792 }
1793 if(!syncf || old)
1794 {
1795 if(!wasnoamb) /* not RINEX compatible without */
1796 ret = 1;
1797 else
1798 ret = 2;
1799 }
1800#ifdef NO_RTCM3_MAIN
1801 else
1802 ret = type;
1803#endif /* NO_RTCM3_MAIN */
1804 }
1805 break;
1806 }
1807 }
1808 return ret;
1809}
1810
1811struct Header
1812{
1813 const char *version;
1814 const char *pgm;
1815 const char *marker;
1816 const char *markertype;
1817 const char *observer;
1818 const char *receiver;
1819 const char *antenna;
1820 const char *position;
1821 const char *antennaposition;
1822 const char *wavelength;
1823 const char *typesofobs; /* should not be modified outside */
1824 const char *typesofobsG; /* should not be modified outside */
1825 const char *typesofobsR; /* should not be modified outside */
1826 const char *typesofobsS; /* should not be modified outside */
1827 const char *typesofobsE; /* should not be modified outside */
1828 const char *typesofobsC; /* should not be modified outside */
1829 const char *typesofobsJ; /* should not be modified outside */
1830 const char *timeoffirstobs; /* should not be modified outside */
1831};
1832
1833#define MAXHEADERLINES 50
1834#define MAXHEADERBUFFERSIZE 4096
1835struct HeaderData
1836{
1837 union
1838 {
1839 struct Header named;
1840 const char *unnamed[MAXHEADERLINES];
1841 } data;
1842 int numheaders;
1843};
1844
1845void converttime(struct converttimeinfo *c, int week, int tow)
1846{
1847 int i, k, doy, j; /* temporary variables */
1848 j = week*(7*24*60*60) + tow + 5*24*60*60;
1849 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1850 j -= k;
1851 c->year = i;
1852 doy = 1+ (j / (24*60*60));
1853 j %= (24*60*60);
1854 c->hour = j / (60*60);
1855 j %= (60*60);
1856 c->minute = j / 60;
1857 c->second = j % 60;
1858 j = 0;
1859 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1860 j += k;
1861 c->month = i;
1862 c->day = doy - j;
1863}
1864
1865#ifndef NO_RTCM3_MAIN
1866void RTCM3Error(const char *fmt, ...)
1867{
1868 va_list v;
1869 va_start(v, fmt);
1870 vfprintf(stderr, fmt, v);
1871 va_end(v);
1872}
1873#endif
1874
1875void RTCM3Text(const char *fmt, ...)
1876{
1877 va_list v;
1878 va_start(v, fmt);
1879 vprintf(fmt, v);
1880 va_end(v);
1881}
1882
1883static void fixrevision(void)
1884{
1885 if(revisionstr[0] == '$')
1886 {
1887 char *a;
1888 int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1889 strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1890 for(a = revisionstr+11; *a && *a != ' '; ++a)
1891 revisionstr[i++] = *a;
1892 revisionstr[i] = 0;
1893 }
1894}
1895
1896static int HandleRunBy(char *buffer, int buffersize, const char **u,
1897int rinex3)
1898{
1899 const char *user;
1900 time_t t;
1901 struct tm * t2;
1902
1903#ifdef NO_RTCM3_MAIN
1904 fixrevision();
1905#endif
1906
1907 user= getenv("USER");
1908 if(!user) user = "";
1909 t = time(&t);
1910 t2 = gmtime(&t);
1911 if(u) *u = user;
1912 return 1+snprintf(buffer, buffersize,
1913 rinex3 ?
1914 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1915 "PGM / RUN BY / DATE" :
1916 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
1917 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1918 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1919}
1920
1921#ifdef NO_RTCM3_MAIN
1922#define NUMSTARTSKIP 1
1923#else
1924#define NUMSTARTSKIP 3
1925#endif
1926
1927int HandleObsHeader(struct RTCM3ParserData *Parser, char *buffer,
1928size_t buffersize, struct HeaderData *hdata)
1929{
1930 int buffersizeold = buffersize;
1931 int i, modified = 0;
1932
1933 if(Parser->rinex3)
1934 {
1935 int flags;
1936#define CHECKFLAGSNEW(a, b, c) \
1937 if(flags & GNSSDF_##b##DATA) \
1938 { \
1939 int new = hdata ? 1 : 0; \
1940 if(!hdata) /* check if already known */ \
1941 { \
1942 int ic; \
1943 for(ic = 0; ic < Parser->info[RTCM3_MSM_##a].numtypes \
1944 && Parser->info[RTCM3_MSM_##a].flags[ic] != GNSSDF_##b##DATA; ++ic) \
1945 ; \
1946 if(ic == Parser->info[RTCM3_MSM_##a].numtypes) \
1947 new = 1; \
1948 } \
1949 if(new) \
1950 { \
1951 Parser->info[RTCM3_MSM_##a].flags[Parser->info[RTCM3_MSM_##a].numtypes] \
1952 = GNSSDF_##b##DATA; \
1953 Parser->info[RTCM3_MSM_##a].pos[Parser->info[RTCM3_MSM_##a].numtypes] \
1954 = GNSSENTRY_##b##DATA; \
1955 if(Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]) \
1956 { \
1957 snprintf(Parser->fieldbuffer##a+4*Parser->info[RTCM3_MSM_##a].numtypes, \
1958 sizeof(Parser->fieldbuffer##a)-4*Parser->info[RTCM3_MSM_##a].numtypes, \
1959 " %-2.2s%c", #c, Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]); \
1960 } \
1961 else \
1962 { \
1963 snprintf(Parser->fieldbuffer##a+4*Parser->info[RTCM3_MSM_##a].numtypes, \
1964 sizeof(Parser->fieldbuffer##a)-4*Parser->info[RTCM3_MSM_##a].numtypes, \
1965 " %-3s", #c); \
1966 } \
1967 ++Parser->info[RTCM3_MSM_##a].numtypes; \
1968 ++modified; \
1969 } \
1970 }
1971
1972#define INITFLAGS(a) \
1973 flags = Parser->startflags; \
1974 modified = 0; \
1975 for(i = 0; i < Parser->Data.numsats; ++i) \
1976 { \
1977 if(Parser->Data.satellites[i] >= PRN_##a##_START \
1978 && Parser->Data.satellites[i] <= PRN_##a##_END) \
1979 flags |= Parser->Data.dataflags[i]; \
1980 }
1981
1982 INITFLAGS(SBAS)
1983 CHECKFLAGSNEW(SBAS, C1, C1C)
1984 CHECKFLAGSNEW(SBAS, L1C, L1C)
1985 CHECKFLAGSNEW(SBAS, D1C, D1C)
1986 CHECKFLAGSNEW(SBAS, S1C, S1C)
1987 CHECKFLAGSNEW(SBAS, C5, C5)
1988 CHECKFLAGSNEW(SBAS, L5, L5)
1989 CHECKFLAGSNEW(SBAS, D5, D5)
1990 CHECKFLAGSNEW(SBAS, S5, S5)
1991
1992 if(modified)
1993 {
1994 if(hdata)
1995 hdata->data.named.typesofobsS = buffer;
1996 i = 1+snprintf(buffer, buffersize,
1997 "S %3d%-52.52s SYS / # / OBS TYPES",
1998 Parser->info[RTCM3_MSM_SBAS].numtypes, Parser->fieldbufferSBAS);
1999 buffer += i; buffersize -= i;
2000 }
2001
2002 INITFLAGS(GPS)
2003 CHECKFLAGSNEW(GPS, C1, C1C)
2004 CHECKFLAGSNEW(GPS, L1C, L1C)
2005 CHECKFLAGSNEW(GPS, D1C, D1C)
2006 CHECKFLAGSNEW(GPS, S1C, S1C)
2007 CHECKFLAGSNEW(GPS, P1, C1W)
2008 CHECKFLAGSNEW(GPS, L1P, L1W)
2009 CHECKFLAGSNEW(GPS, D1P, D1W)
2010 CHECKFLAGSNEW(GPS, S1P, S1W)
2011 CHECKFLAGSNEW(GPS, C5, C5)
2012 CHECKFLAGSNEW(GPS, L5, L5)
2013 CHECKFLAGSNEW(GPS, D5, D5)
2014 CHECKFLAGSNEW(GPS, S5, S5)
2015 CHECKFLAGSNEW(GPS, P2, C2W)
2016 CHECKFLAGSNEW(GPS, L2P, L2W)
2017 CHECKFLAGSNEW(GPS, D2P, D2W)
2018 CHECKFLAGSNEW(GPS, S2P, S2W)
2019 CHECKFLAGSNEW(GPS, C2, C2)
2020 CHECKFLAGSNEW(GPS, L2C, L2)
2021 CHECKFLAGSNEW(GPS, D2C, D2)
2022 CHECKFLAGSNEW(GPS, S2C, S2)
2023 CHECKFLAGSNEW(GPS, C1N, C1)
2024 CHECKFLAGSNEW(GPS, L1N, L1)
2025 CHECKFLAGSNEW(GPS, D1N, D1)
2026 CHECKFLAGSNEW(GPS, S1N, S1)
2027
2028 if(modified)
2029 {
2030 if(hdata)
2031 hdata->data.named.typesofobsG = buffer;
2032 i = 1+snprintf(buffer, buffersize,
2033 "G %3d%-52.52s SYS / # / OBS TYPES",
2034 Parser->info[RTCM3_MSM_GPS].numtypes, Parser->fieldbufferGPS);
2035 if(Parser->info[RTCM3_MSM_GPS].numtypes>13)
2036 {
2037 i += snprintf(buffer+i-1, buffersize,
2038 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGPS+13*4);
2039 }
2040 buffer += i; buffersize -= i;
2041 }
2042
2043 INITFLAGS(GLONASS)
2044 CHECKFLAGSNEW(GLONASS, C1, C1C)
2045 CHECKFLAGSNEW(GLONASS, L1C, L1C)
2046 CHECKFLAGSNEW(GLONASS, D1C, D1C)
2047 CHECKFLAGSNEW(GLONASS, S1C, S1C)
2048 CHECKFLAGSNEW(GLONASS, P1, C1P)
2049 CHECKFLAGSNEW(GLONASS, L1P, L1P)
2050 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2051 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2052 CHECKFLAGSNEW(GLONASS, P2, C2P)
2053 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2054 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2055 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2056 CHECKFLAGSNEW(GLONASS, C2, C2C)
2057 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2058 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2059 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2060
2061 if(modified)
2062 {
2063 if(hdata)
2064 hdata->data.named.typesofobsR = buffer;
2065 i = 1+snprintf(buffer, buffersize,
2066 "R %3d%-52.52s SYS / # / OBS TYPES",
2067 Parser->info[RTCM3_MSM_GLONASS].numtypes, Parser->fieldbufferGLONASS);
2068 if(Parser->info[RTCM3_MSM_GLONASS].numtypes>13)
2069 {
2070 i += snprintf(buffer+i-1, buffersize,
2071 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGLONASS+13*4);
2072 }
2073 buffer += i; buffersize -= i;
2074 }
2075
2076 INITFLAGS(GALGIO)
2077 CHECKFLAGSNEW(GALILEO, C1, C1)
2078 CHECKFLAGSNEW(GALILEO, L1C, L1)
2079 CHECKFLAGSNEW(GALILEO, D1C, D1)
2080 CHECKFLAGSNEW(GALILEO, S1C, S1)
2081 CHECKFLAGSNEW(GALILEO, C6, C6)
2082 CHECKFLAGSNEW(GALILEO, L6, L6)
2083 CHECKFLAGSNEW(GALILEO, D6, D6)
2084 CHECKFLAGSNEW(GALILEO, S6, S6)
2085 CHECKFLAGSNEW(GALILEO, C5, C5)
2086 CHECKFLAGSNEW(GALILEO, L5, L5)
2087 CHECKFLAGSNEW(GALILEO, D5, D5)
2088 CHECKFLAGSNEW(GALILEO, S5, S5)
2089 CHECKFLAGSNEW(GALILEO, C5B, C7)
2090 CHECKFLAGSNEW(GALILEO, L5B, L7)
2091 CHECKFLAGSNEW(GALILEO, D5B, D7)
2092 CHECKFLAGSNEW(GALILEO, S5B, S7)
2093 CHECKFLAGSNEW(GALILEO, C5AB, C8)
2094 CHECKFLAGSNEW(GALILEO, L5AB, L8)
2095 CHECKFLAGSNEW(GALILEO, D5AB, D8)
2096 CHECKFLAGSNEW(GALILEO, S5AB, S8)
2097
2098 if(modified)
2099 {
2100 if(hdata)
2101 hdata->data.named.typesofobsE = buffer;
2102 i = 1+snprintf(buffer, buffersize,
2103 "E %3d%-52.52s SYS / # / OBS TYPES",
2104 Parser->info[RTCM3_MSM_GALILEO].numtypes, Parser->fieldbufferGALILEO);
2105 if(Parser->info[RTCM3_MSM_GALILEO].numtypes>13)
2106 {
2107 i += snprintf(buffer+i-1, buffersize,
2108 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGALILEO+13*4);
2109 }
2110 buffer += i; buffersize -= i;
2111 }
2112
2113 INITFLAGS(COMPASS)
2114 CHECKFLAGSNEW(COMPASS, CB1, C2I)
2115 CHECKFLAGSNEW(COMPASS, LB1, L2I)
2116 CHECKFLAGSNEW(COMPASS, DB1, D2I)
2117 CHECKFLAGSNEW(COMPASS, SB1, S2I)
2118 CHECKFLAGSNEW(COMPASS, CB2, C7I)
2119 CHECKFLAGSNEW(COMPASS, LB2, L7I)
2120 CHECKFLAGSNEW(COMPASS, DB2, D7I)
2121 CHECKFLAGSNEW(COMPASS, SB2, S7I)
2122 CHECKFLAGSNEW(COMPASS, CB3, C6I)
2123 CHECKFLAGSNEW(COMPASS, LB3, L6I)
2124 CHECKFLAGSNEW(COMPASS, DB3, D6I)
2125 CHECKFLAGSNEW(COMPASS, SB3, S6I)
2126
2127 if(modified)
2128 {
2129 if(hdata)
2130 hdata->data.named.typesofobsC = buffer;
2131 i = 1+snprintf(buffer, buffersize,
2132 "C %3d%-52.52s SYS / # / OBS TYPES",
2133 Parser->info[RTCM3_MSM_COMPASS].numtypes, Parser->fieldbufferCOMPASS);
2134 if(Parser->info[RTCM3_MSM_COMPASS].numtypes>13)
2135 {
2136 i += snprintf(buffer+i-1, buffersize,
2137 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferCOMPASS+13*4);
2138 }
2139 buffer += i; buffersize -= i;
2140 }
2141
2142 INITFLAGS(QZSS)
2143
2144 CHECKFLAGSNEW(QZSS, C1, C1C)
2145 CHECKFLAGSNEW(QZSS, L1C, L1C)
2146 CHECKFLAGSNEW(QZSS, D1C, D1C)
2147 CHECKFLAGSNEW(QZSS, S1C, S1C)
2148
2149 CHECKFLAGSNEW(QZSS, CSAIF, C1Z)
2150 CHECKFLAGSNEW(QZSS, LSAIF, L1Z)
2151 CHECKFLAGSNEW(QZSS, DSAIF, D1Z)
2152 CHECKFLAGSNEW(QZSS, SSAIF, S1Z)
2153
2154 CHECKFLAGSNEW(QZSS, C1N, C1)
2155 CHECKFLAGSNEW(QZSS, L1N, L1)
2156 CHECKFLAGSNEW(QZSS, D1N, D1)
2157 CHECKFLAGSNEW(QZSS, S1N, S1)
2158
2159 CHECKFLAGSNEW(QZSS, C6, C6)
2160 CHECKFLAGSNEW(QZSS, L6, L6)
2161 CHECKFLAGSNEW(QZSS, D6, D6)
2162 CHECKFLAGSNEW(QZSS, S6, S6)
2163
2164 CHECKFLAGSNEW(QZSS, C2, C2)
2165 CHECKFLAGSNEW(QZSS, L2C, L2)
2166 CHECKFLAGSNEW(QZSS, D2C, D2)
2167 CHECKFLAGSNEW(QZSS, S2C, S2)
2168
2169 CHECKFLAGSNEW(QZSS, C5, C5)
2170 CHECKFLAGSNEW(QZSS, L5, L5)
2171 CHECKFLAGSNEW(QZSS, D5, D5)
2172 CHECKFLAGSNEW(QZSS, S5, S5)
2173
2174 if(modified)
2175 {
2176 if(hdata)
2177 hdata->data.named.typesofobsJ = buffer;
2178 i = 1+snprintf(buffer, buffersize,
2179 "J %3d%-52.52s SYS / # / OBS TYPES",
2180 Parser->info[RTCM3_MSM_QZSS].numtypes, Parser->fieldbufferQZSS);
2181 if(Parser->info[RTCM3_MSM_QZSS].numtypes>13)
2182 {
2183 i += snprintf(buffer+i-1, buffersize,
2184 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferQZSS+13*4);
2185 }
2186 buffer += i; buffersize -= i;
2187 }
2188 }
2189 else
2190 {
2191#define CHECKFLAGS(a, b) \
2192 if(flags & GNSSDF_##a##DATA) \
2193 { \
2194 if(Parser->datafields[RINEXENTRY_##b##DATA]) \
2195 { \
2196 Parser->info[RTCM3_MSM_GPS].flags[Parser->datafields[\
2197 RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
2198 Parser->info[RTCM3_MSM_GPS].pos[Parser->datafields[\
2199 RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
2200 } \
2201 else \
2202 { \
2203 Parser->flags[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSDF_##a##DATA; \
2204 Parser->pos[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSENTRY_##a##DATA; \
2205 Parser->datafields[RINEXENTRY_##b##DATA] = \
2206 ++Parser->info[RTCM3_MSM_GPS].numtypes; \
2207 snprintf(Parser->fieldbuffer+6*Parser->numdatafields, \
2208 sizeof(Parser->fieldbuffer)-6*Parser->numdatafields, " "#b); \
2209 ++Parser->numdatafields; \
2210 ++modified; \
2211 } \
2212 }
2213
2214 int flags = Parser->startflags;
2215 for(i = 0; i < Parser->Data.numsats; ++i)
2216 flags |= Parser->Data.dataflags[i];
2217
2218 CHECKFLAGS(C1,C1)
2219 CHECKFLAGS(C2,C2)
2220 CHECKFLAGS(P1,P1)
2221 CHECKFLAGS(P2,P2)
2222 CHECKFLAGS(L1C,L1)
2223 CHECKFLAGS(L1P,L1)
2224 CHECKFLAGS(L2C,L2)
2225 CHECKFLAGS(L2P,L2)
2226 CHECKFLAGS(D1C,D1)
2227 CHECKFLAGS(D1P,D1)
2228 CHECKFLAGS(D2C,D2)
2229 CHECKFLAGS(D2P,D2)
2230 CHECKFLAGS(S1C,S1)
2231 CHECKFLAGS(S1P,S1)
2232 CHECKFLAGS(S2C,S2)
2233 CHECKFLAGS(S2P,S2)
2234 CHECKFLAGS(C5,C5)
2235 CHECKFLAGS(L5,L5)
2236 CHECKFLAGS(D5,D5)
2237 CHECKFLAGS(S5,S5)
2238 CHECKFLAGS(C5AB,C8)
2239 CHECKFLAGS(L5AB,L8)
2240 CHECKFLAGS(D5AB,D8)
2241 CHECKFLAGS(S5AB,S8)
2242 CHECKFLAGS(C5B,C7)
2243 CHECKFLAGS(L5B,L7)
2244 CHECKFLAGS(D5B,D7)
2245 CHECKFLAGS(S5B,S7)
2246 CHECKFLAGS(C6,C6)
2247 CHECKFLAGS(L6,L6)
2248 CHECKFLAGS(D6,D6)
2249 CHECKFLAGS(S6,S6)
2250 /* Skip C1N and SAIF for RINEX2! */
2251
2252 if(hdata)
2253 hdata->data.named.typesofobs = buffer;
2254 if(modified)
2255 {
2256 i = 1+snprintf(buffer, buffersize,
2257 "%6d%-54.54s# / TYPES OF OBSERV", Parser->info[RTCM3_MSM_GPS].numtypes,
2258 Parser->fieldbuffer);
2259 if(Parser->info[RTCM3_MSM_GPS].numtypes>9)
2260 {
2261 i += snprintf(buffer+i-1, buffersize,
2262 "\n %-54.54s# / TYPES OF OBSERV", Parser->fieldbuffer+9*6);
2263 }
2264 if(Parser->info[RTCM3_MSM_GPS].numtypes>18)
2265 {
2266 i += snprintf(buffer+i-1, buffersize,
2267 "\n %-54.54s# / TYPES OF OBSERV", Parser->fieldbuffer+18*6);
2268 }
2269 buffer += i; buffersize -= i;
2270 }
2271 }
2272 return buffersizeold - buffersize;
2273}
2274
2275void HandleHeader(struct RTCM3ParserData *Parser)
2276{
2277#ifdef NO_RTCM3_MAIN
2278 int flags, modified = 0;
2279 if(Parser->allflags == 0)
2280 Parser->allflags = ~0;
2281 flags = Parser->allflags;
2282 if(Parser->rinex3)
2283 {
2284 struct HeaderData *hdata = 0;
2285 CHECKFLAGSNEW(GPS, C1, C1C)
2286 CHECKFLAGSNEW(GPS, L1C, L1C)
2287 CHECKFLAGSNEW(GPS, D1C, D1C)
2288 CHECKFLAGSNEW(GPS, S1C, S1C)
2289 CHECKFLAGSNEW(GPS, P1, C1P)
2290 CHECKFLAGSNEW(GPS, L1P, L1P)
2291 CHECKFLAGSNEW(GPS, D1P, D1P)
2292 CHECKFLAGSNEW(GPS, S1P, S1P)
2293 CHECKFLAGSNEW(GPS, P2, C2P)
2294 CHECKFLAGSNEW(GPS, L2P, L2P)
2295 CHECKFLAGSNEW(GPS, D2P, D2P)
2296 CHECKFLAGSNEW(GPS, S2P, S2P)
2297 CHECKFLAGSNEW(GPS, C2, C2X)
2298 CHECKFLAGSNEW(GPS, L2C, L2X)
2299 CHECKFLAGSNEW(GPS, D2C, D2X)
2300 CHECKFLAGSNEW(GPS, S2C, S2X)
2301 CHECKFLAGSNEW(GLONASS, C1, C1C)
2302 CHECKFLAGSNEW(GLONASS, L1C, L1C)
2303 CHECKFLAGSNEW(GLONASS, D1C, D1C)
2304 CHECKFLAGSNEW(GLONASS, S1C, S1C)
2305 CHECKFLAGSNEW(GLONASS, P1, C1P)
2306 CHECKFLAGSNEW(GLONASS, L1P, L1P)
2307 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2308 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2309 CHECKFLAGSNEW(GLONASS, P2, C2P)
2310 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2311 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2312 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2313 CHECKFLAGSNEW(GLONASS, C2, C2C)
2314 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2315 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2316 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2317 }
2318 else
2319 {
2320 CHECKFLAGS(C1,C1)
2321 CHECKFLAGS(C2,C2)
2322 CHECKFLAGS(P1,P1)
2323 CHECKFLAGS(P2,P2)
2324 CHECKFLAGS(L1C,L1)
2325 CHECKFLAGS(L1P,L1)
2326 CHECKFLAGS(L2C,L2)
2327 CHECKFLAGS(L2P,L2)
2328 CHECKFLAGS(D1C,D1)
2329 CHECKFLAGS(D1P,D1)
2330 CHECKFLAGS(D2C,D2)
2331 CHECKFLAGS(D2P,D2)
2332 CHECKFLAGS(S1C,S1)
2333 CHECKFLAGS(S1P,S1)
2334 CHECKFLAGS(S2C,S2)
2335 CHECKFLAGS(S2P,S2)
2336 CHECKFLAGS(C5,C5)
2337 CHECKFLAGS(L5,L5)
2338 CHECKFLAGS(D5,D5)
2339 CHECKFLAGS(S5,S5)
2340 CHECKFLAGS(C5AB,C8)
2341 CHECKFLAGS(L5AB,L8)
2342 CHECKFLAGS(D5AB,D8)
2343 CHECKFLAGS(S5AB,S8)
2344 CHECKFLAGS(C5B,C7)
2345 CHECKFLAGS(L5B,L7)
2346 CHECKFLAGS(D5B,D7)
2347 CHECKFLAGS(S5B,S7)
2348 CHECKFLAGS(C6,C6)
2349 CHECKFLAGS(L6,L6)
2350 CHECKFLAGS(D6,D6)
2351 CHECKFLAGS(S6,S6)
2352 }
2353#else /* NO_RTCM3_MAIN */
2354 struct HeaderData hdata;
2355 char thebuffer[MAXHEADERBUFFERSIZE];
2356 char *buffer = thebuffer;
2357 size_t buffersize = sizeof(thebuffer);
2358 int i;
2359
2360 memset(&hdata, 0, sizeof(hdata));
2361
2362 hdata.data.named.version = buffer;
2363 i = 1+snprintf(buffer, buffersize,
2364 "%9.2f OBSERVATION DATA M (Mixed)"
2365 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
2366 buffer += i; buffersize -= i;
2367
2368 {
2369 const char *str;
2370 hdata.data.named.pgm = buffer;
2371 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
2372 buffer += i; buffersize -= i;
2373 hdata.data.named.observer = buffer;
2374 i = 1+snprintf(buffer, buffersize,
2375 "%-20.20s "
2376 "OBSERVER / AGENCY", str);
2377 buffer += i; buffersize -= i;
2378 }
2379
2380 hdata.data.named.marker =
2381 "RTCM3TORINEX "
2382 "MARKER NAME";
2383
2384 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
2385 "GEODETIC "
2386 "MARKER TYPE";
2387
2388 hdata.data.named.receiver =
2389 " "
2390 "REC # / TYPE / VERS";
2391
2392 hdata.data.named.antenna =
2393 " "
2394 "ANT # / TYPE";
2395
2396 hdata.data.named.position =
2397 " .0000 .0000 .0000 "
2398 "APPROX POSITION XYZ";
2399
2400 hdata.data.named.antennaposition =
2401 " .0000 .0000 .0000 "
2402 "ANTENNA: DELTA H/E/N";
2403
2404 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
2405 " 1 1 "
2406 "WAVELENGTH FACT L1/2";
2407
2408 hdata.numheaders = 18;
2409
2410 i = HandleObsHeader(Parser, buffer, buffersize, &hdata);
2411 buffer += i; buffersize -= i;
2412
2413 {
2414 struct converttimeinfo cti;
2415 converttime(&cti, Parser->Data.week,
2416 (int)floor(Parser->Data.timeofweek/1000.0));
2417 hdata.data.named.timeoffirstobs = buffer;
2418 i = 1+snprintf(buffer, buffersize,
2419 " %4d %2d %2d %2d %2d %10.7f GPS "
2420 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
2421 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
2422
2423 buffer += i; buffersize -= i;
2424 }
2425
2426 if(Parser->headerfile)
2427 {
2428 FILE *fh;
2429 if((fh = fopen(Parser->headerfile, "r")))
2430 {
2431 size_t siz;
2432 char *lastblockstart;
2433 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
2434 {
2435 buffer[siz] = '\n';
2436 if(siz == buffersize)
2437 {
2438 RTCM3Error("Header file is too large. Only %d bytes read.",
2439 (int)siz);
2440 }
2441 /* scan the file line by line and enter the entries in the list */
2442 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
2443 /* overwrites entries, except for comments */
2444 lastblockstart = buffer;
2445 for(i = 0; i < (int)siz; ++i)
2446 {
2447 if(buffer[i] == '\n')
2448 { /* we found a line */
2449 char *end;
2450 while(buffer[i+1] == '\r')
2451 ++i; /* skip \r in case there are any */
2452 end = buffer+i;
2453 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
2454 *(end--) = 0;
2455 if(end-lastblockstart < 60+5) /* short line */
2456 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
2457 else
2458 {
2459 int pos;
2460 if(!strcmp("COMMENT", lastblockstart+60))
2461 pos = hdata.numheaders;
2462 else
2463 {
2464 for(pos = 0; pos < hdata.numheaders; ++pos)
2465 {
2466 if(hdata.data.unnamed[pos] &&
2467 !strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2468 break;
2469 }
2470 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2471 || !strcmp("SYS / # / OBS TYPES", lastblockstart+60)
2472 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2473 {
2474 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2475 lastblockstart+60);
2476 }
2477 }
2478 if(pos >= MAXHEADERLINES)
2479 {
2480 RTCM3Error("Maximum number of header lines of %d reached.\n",
2481 MAXHEADERLINES);
2482 }
2483 else if(!strcmp("END OF HEADER", lastblockstart+60))
2484 {
2485 RTCM3Error("End of header ignored.\n");
2486 }
2487 else
2488 {
2489 hdata.data.unnamed[pos] = lastblockstart;
2490 if(pos == hdata.numheaders)
2491 ++hdata.numheaders;
2492 }
2493 }
2494 lastblockstart = buffer+i+1;
2495 }
2496 }
2497 }
2498 else
2499 {
2500 RTCM3Error("Could not read data from headerfile '%s'.\n",
2501 Parser->headerfile);
2502 }
2503 fclose(fh);
2504 }
2505 else
2506 {
2507 RTCM3Error("Could not open header datafile '%s'.\n",
2508 Parser->headerfile);
2509 }
2510 }
2511
2512 for(i = 0; i < hdata.numheaders; ++i)
2513 {
2514 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2515 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2516 }
2517 RTCM3Text(" "
2518 "END OF HEADER\n");
2519#endif
2520}
2521
2522static void ConvLine(FILE *file, const char *fmt, ...)
2523{
2524 char buffer[100], *b;
2525 va_list v;
2526 va_start(v, fmt);
2527 vsnprintf(buffer, sizeof(buffer), fmt, v);
2528 for(b = buffer; *b; ++b)
2529 {
2530 if(*b == 'e') *b = 'D';
2531 }
2532 fprintf(file, "%s", buffer);
2533 va_end(v);
2534}
2535
2536void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2537{
2538 Parser->Message[Parser->MessageSize++] = byte;
2539 if(Parser->MessageSize >= Parser->NeedBytes)
2540 {
2541 int r;
2542 while((r = RTCM3Parser(Parser)))
2543 {
2544 if(r == 1020 || r == 1019 || r == 1044 || r == 1043)
2545 {
2546 FILE *file = 0;
2547
2548 if(Parser->rinex3 && !(file = Parser->gpsfile))
2549 {
2550 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris
2551 : Parser->qzssephemeris ? Parser->qzssephemeris : Parser->glonassephemeris;
2552 if(n)
2553 {
2554 if(!(Parser->gpsfile = fopen(n, "w")))
2555 {
2556 RTCM3Error("Could not open ephemeris output file.\n");
2557 }
2558 else
2559 {
2560 char buffer[100];
2561 fprintf(Parser->gpsfile,
2562 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2563 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2564 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2565 }
2566 Parser->qzssephemeris = 0;
2567 Parser->gpsephemeris = 0;
2568 Parser->glonassephemeris = 0;
2569 Parser->sbasephemeris = 0;
2570 file = Parser->gpsfile;
2571 }
2572 }
2573 else
2574 {
2575 if(r == 1020)
2576 {
2577 if(Parser->glonassephemeris)
2578 {
2579 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2580 {
2581 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2582 }
2583 else
2584 {
2585 char buffer[100];
2586 fprintf(Parser->glonassfile,
2587 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2588 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2589 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2590 }
2591 Parser->glonassephemeris = 0;
2592 }
2593 file = Parser->glonassfile;
2594 }
2595 else if(r == 1019)
2596 {
2597 if(Parser->gpsephemeris)
2598 {
2599 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2600 {
2601 RTCM3Error("Could not open GPS ephemeris output file.\n");
2602 }
2603 else
2604 {
2605 char buffer[100];
2606 fprintf(Parser->gpsfile,
2607 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2608 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2609 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2610 }
2611 Parser->gpsephemeris = 0;
2612 }
2613 file = Parser->gpsfile;
2614 }
2615 else if(r == 1043)
2616 {
2617 if(Parser->sbasephemeris)
2618 {
2619 if(!(Parser->sbasfile = fopen(Parser->sbasephemeris, "w")))
2620 {
2621 RTCM3Error("Could not open SBAS ephemeris output file.\n");
2622 }
2623 else
2624 {
2625 char buffer[100];
2626 fprintf(Parser->sbasfile,
2627 "%9.2f%11sN: SBAS NAV DATA%24sRINEX VERSION / TYPE\n", 2.1, "", "");
2628 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2629 fprintf(Parser->sbasfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2630 }
2631 Parser->sbasephemeris = 0;
2632 }
2633 file = Parser->sbasfile;
2634 }
2635 else if(r == 1044)
2636 {
2637 if(Parser->qzssephemeris)
2638 {
2639 if(!(Parser->qzssfile = fopen(Parser->qzssephemeris, "w")))
2640 {
2641 RTCM3Error("Could not open QZSS ephemeris output file.\n");
2642 }
2643 else
2644 {
2645 char buffer[100];
2646 fprintf(Parser->qzssfile,
2647 "%9.2f%11sN: QZSS NAV DATA%24sRINEX VERSION / TYPE\n", 2.1, "", "");
2648 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2649 fprintf(Parser->qzssfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2650 }
2651 Parser->qzssephemeris = 0;
2652 }
2653 file = Parser->qzssfile;
2654 }
2655 }
2656 if(file)
2657 {
2658 const char *sep = " ";
2659 if(r == 1020)
2660 {
2661 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2662 int w = e->GPSWeek, tow = e->GPSTOW, i;
2663 struct converttimeinfo cti;
2664
2665 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2666 converttime(&cti, w, tow);
2667
2668 i = e->tk-3*60*60; if(i < 0) i += 86400;
2669
2670 if(Parser->rinex3)
2671 {
2672 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2673 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2674 cti.second, -e->tau, e->gamma, (double) i);
2675 sep = " ";
2676 }
2677 else
2678 {
2679 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2680 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2681 (double) cti.second, -e->tau, e->gamma, (double) i);
2682 }
2683 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->x_pos,
2684 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2685 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->y_pos,
2686 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2687 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->z_pos,
2688 e->z_velocity, e->z_acceleration, (double) e->E);
2689 }
2690 else if(r == 1043)
2691 {
2692 struct sbasephemeris *e = &Parser->ephemerisSBAS;
2693 struct converttimeinfo cti;
2694 converttime(&cti, e->GPSweek_TOE, e->TOE);
2695 if(Parser->rinex3)
2696 {
2697 ConvLine(file, "S%02d %04d %2d %2d %2d %2d %2d%19.12e%19.12e%19.12e\n",
2698 e->satellite-100, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2699 cti.second, e->agf0, e->agf1, (double)e->TOW);
2700 sep = " ";
2701 }
2702 else
2703 {
2704 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2705 e->satellite-100, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2706 (double)cti.second, e->agf0, e->agf1, (double)e->TOW);
2707 }
2708 /* X, health */
2709 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->x_pos,
2710 e->x_velocity, e->x_acceleration, e->URA == 15 ? 1.0 : 0.0);
2711 /* Y, accuracy */
2712 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->y_pos,
2713 e->y_velocity, e->y_acceleration, (double)e->URA);
2714 /* Z */
2715 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->z_pos,
2716 e->z_velocity, e->z_acceleration, (double)e->IODN);
2717 }
2718 else /* if(r == 1019 || r == 1044) */
2719 {
2720 struct gpsephemeris *e = &Parser->ephemerisGPS;
2721 double d; /* temporary variable */
2722 unsigned long int i; /* temporary variable */
2723 struct converttimeinfo cti;
2724 converttime(&cti, e->GPSweek, e->TOC);
2725 int qzss = 0;
2726 int num = e->satellite;
2727
2728 if(num >= PRN_QZSS_START)
2729 {
2730 qzss = 1;
2731 num -= PRN_QZSS_START-1;
2732 }
2733 if(Parser->rinex3)
2734 {
2735 ConvLine(file,
2736 "%s%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2737 qzss ? "J" : "G", num, cti.year, cti.month, cti.day, cti.hour,
2738 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2739 e->clock_driftrate);
2740 sep = " ";
2741 }
2742 else
2743 {
2744 ConvLine(file,
2745 "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2746 num, cti.year%100, cti.month, cti.day, cti.hour,
2747 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2748 e->clock_driftrate);
2749 }
2750 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2751 (double)e->IODE, e->Crs, e->Delta_n, e->M0);
2752 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->Cuc,
2753 e->e, e->Cus, e->sqrt_A);
2754 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2755 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2756 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->i0,
2757 e->Crc, e->omega, e->OMEGADOT);
2758 d = 0;
2759 i = e->flags;
2760 if(i & GPSEPHF_L2CACODE)
2761 d += 2.0;
2762 if(i & GPSEPHF_L2PCODE)
2763 d += 1.0;
2764 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->IDOT, d,
2765 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2766 if(e->URAindex <= 6) /* URA index */
2767 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2768 else
2769 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2770 /* 15 indicates not to use satellite. We can't handle this special
2771 case, so we create a high "non"-accuracy value. */
2772 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, d,
2773 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2774
2775 ConvLine(file, "%s%19.12e%19.12e\n", sep, ((double)e->TOW),
2776 (i & GPSEPHF_6HOURSFIT) ? (Parser->rinex3 ? 1 : qzss ? 4.0 : 6.0)
2777 : (Parser->rinex3 ? 0 : qzss ? 2.0 : 4.0));
2778 /* TOW */
2779 }
2780 }
2781 }
2782 else if (r == 1 || r == 2)
2783 {
2784 int i, j, o, nh=0, hl=2;
2785 char newheader[512];
2786 struct converttimeinfo cti;
2787
2788 /* skip first epochs to detect correct data types */
2789 if(Parser->init < (Parser->changeobs ? 1 : NUMSTARTSKIP))
2790 {
2791 ++Parser->init;
2792
2793 if(Parser->init == (Parser->changeobs ? 1 : NUMSTARTSKIP))
2794 HandleHeader(Parser);
2795 else
2796 {
2797 for(i = 0; i < Parser->Data.numsats; ++i)
2798 Parser->startflags |= Parser->Data.dataflags[i];
2799 continue;
2800 }
2801 }
2802 if(r == 2 && !Parser->validwarning)
2803 {
2804 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2805 " COMMENT\n");
2806 Parser->validwarning = 1;
2807 }
2808
2809 converttime(&cti, Parser->Data.week,
2810 (int)floor(Parser->Data.timeofweek/1000.0));
2811 newheader[0] = 0;
2812 if(Parser->changeobs)
2813 {
2814 nh = HandleObsHeader(Parser, newheader, sizeof(newheader), 0);
2815 for(i = 0; i < nh; ++i)
2816 {
2817 if(newheader[i] == '\n')
2818 ++hl;
2819 }
2820 }
2821 if(Parser->rinex3)
2822 {
2823 if(nh)
2824 {
2825 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 4%3d\n",
2826 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2827 + fmod(Parser->Data.timeofweek/1000.0,1.0), hl);
2828 RTCM3Text("%s\n "
2829 " END OF HEADER\n", newheader);
2830 }
2831 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f %d%3d\n",
2832 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2833 + fmod(Parser->Data.timeofweek/1000.0,1.0), 0,
2834 Parser->Data.numsats);
2835 for(i = 0; i < Parser->Data.numsats; ++i)
2836 {
2837 int sys[RTCM3_MSM_NUMSYS] = {0,0,0,0,0,0};
2838 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2839 {
2840 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2841 sys[RTCM3_MSM_GPS] = 1;
2842 }
2843 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2844 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2845 {
2846 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2847 sys[RTCM3_MSM_GLONASS] = 1;
2848 }
2849 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2850 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2851 {
2852 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2853 sys[RTCM3_MSM_GALILEO] = 1;
2854 }
2855 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2856 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2857 {
2858 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2859 sys[RTCM3_MSM_GALILEO] = 1;
2860 }
2861 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2862 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2863 {
2864 RTCM3Text("J%02d", Parser->Data.satellites[i] - (PRN_QZSS_START-1));
2865 sys[RTCM3_MSM_QZSS] = 1;
2866 }
2867 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2868 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2869 {
2870 RTCM3Text("C%02d", Parser->Data.satellites[i] - (PRN_COMPASS_START-1));
2871 sys[RTCM3_MSM_COMPASS] = 1;
2872 }
2873 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2874 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2875 {
2876 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_SBAS_START+20);
2877 sys[RTCM3_MSM_SBAS] = 1;
2878 }
2879 else
2880 {
2881 RTCM3Text("%3d", Parser->Data.satellites[i]);
2882 }
2883
2884 if(sys[RTCM3_MSM_GLONASS])
2885 {
2886 for(j = 0; j < Parser->info[RTCM3_MSM_GLONASS].numtypes; ++j)
2887 {
2888 long long df = Parser->info[RTCM3_MSM_GLONASS].flags[j];
2889 int pos = Parser->info[RTCM3_MSM_GLONASS].pos[j];
2890 if((Parser->Data.dataflags[i] & df)
2891 && !isnan(Parser->Data.measdata[i][pos])
2892 && !isinf(Parser->Data.measdata[i][pos])
2893 && (Parser->Data.codetype[i][pos]
2894 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
2895 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
2896 == Parser->Data.codetype[i][pos][1]))
2897 {
2898 char lli = ' ';
2899 char snr = ' ';
2900 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2901 {
2902 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2903 lli = '1';
2904 snr = '0'+Parser->Data.snrL1[i];
2905 }
2906 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2907 {
2908 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2909 lli = '1';
2910 snr = '0'+Parser->Data.snrL2[i];
2911 }
2912 RTCM3Text("%14.3f%c%c",
2913 Parser->Data.measdata[i][pos],lli,snr);
2914 }
2915 else
2916 { /* no or illegal data */
2917 RTCM3Text(" ");
2918 }
2919 }
2920 }
2921 else if(sys[RTCM3_MSM_GALILEO])
2922 {
2923 for(j = 0; j < Parser->info[RTCM3_MSM_GALILEO].numtypes; ++j)
2924 {
2925 long long df = Parser->info[RTCM3_MSM_GALILEO].flags[j];
2926 int pos = Parser->info[RTCM3_MSM_GALILEO].pos[j];
2927 if((Parser->Data.dataflags[i] & df)
2928 && !isnan(Parser->Data.measdata[i][pos])
2929 && !isinf(Parser->Data.measdata[i][pos])
2930 && (Parser->Data.codetype[i][pos]
2931 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
2932 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
2933 == Parser->Data.codetype[i][pos][1]))
2934 {
2935 char lli = ' ';
2936 char snr = ' ';
2937 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2938 {
2939 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2940 lli = '1';
2941 snr = '0'+Parser->Data.snrL1[i];
2942 }
2943 if(df & GNSSDF_L6DATA)
2944 {
2945 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2946 lli = '1';
2947 snr = ' ';
2948 }
2949 if(df & GNSSDF_L5DATA)
2950 {
2951 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2952 lli = '1';
2953 snr = ' ';
2954 }
2955 if(df & GNSSDF_L5BDATA)
2956 {
2957 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2958 lli = '1';
2959 snr = ' ';
2960 }
2961 if(df & GNSSDF_L5ABDATA)
2962 {
2963 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2964 lli = '1';
2965 snr = ' ';
2966 }
2967 RTCM3Text("%14.3f%c%c",
2968 Parser->Data.measdata[i][pos],lli,snr);
2969 }
2970 else
2971 { /* no or illegal data */
2972 RTCM3Text(" ");
2973 }
2974 }
2975 }
2976 else if(sys[RTCM3_MSM_COMPASS])
2977 {
2978 for(j = 0; j < Parser->info[RTCM3_MSM_COMPASS].numtypes; ++j)
2979 {
2980 long long df = Parser->info[RTCM3_MSM_COMPASS].flags[j];
2981 int pos = Parser->info[RTCM3_MSM_COMPASS].pos[j];
2982 if((Parser->Data.dataflags[i] & df)
2983 && !isnan(Parser->Data.measdata[i][pos])
2984 && !isinf(Parser->Data.measdata[i][pos])
2985 && (Parser->Data.codetype[i][pos]
2986 && Parser->info[RTCM3_MSM_COMPASS].type[pos]
2987 && Parser->info[RTCM3_MSM_COMPASS].type[pos]
2988 == Parser->Data.codetype[i][pos][1]))
2989 {
2990 char lli = ' ';
2991 char snr = ' ';
2992 if(df & GNSSDF_LB1DATA)
2993 {
2994 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB1)
2995 lli = '1';
2996 }
2997 if(df & GNSSDF_LB2DATA)
2998 {
2999 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB2)
3000 lli = '1';
3001 }
3002 if(df & GNSSDF_LB3DATA)
3003 {
3004 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB3)
3005 lli = '1';
3006 }
3007 RTCM3Text("%14.3f%c%c",
3008 Parser->Data.measdata[i][pos],lli,snr);
3009 }
3010 else
3011 { /* no or illegal data */
3012 RTCM3Text(" ");
3013 }
3014 }
3015 }
3016 else if(sys[RTCM3_MSM_QZSS])
3017 {
3018 for(j = 0; j < Parser->info[RTCM3_MSM_QZSS].numtypes; ++j)
3019 {
3020 long long df = Parser->info[RTCM3_MSM_QZSS].flags[j];
3021 int pos = Parser->info[RTCM3_MSM_QZSS].pos[j];
3022 if((Parser->Data.dataflags[i] & df)
3023 && !isnan(Parser->Data.measdata[i][pos])
3024 && !isinf(Parser->Data.measdata[i][pos])
3025 && (Parser->Data.codetype[i][pos]
3026 && Parser->info[RTCM3_MSM_QZSS].type[pos]
3027 && Parser->info[RTCM3_MSM_QZSS].type[pos]
3028 == Parser->Data.codetype[i][pos][1]))
3029 {
3030 char lli = ' ';
3031 char snr = ' ';
3032 if(df & GNSSDF_L1CDATA)
3033 {
3034 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3035 lli = '1';
3036 snr = '0'+Parser->Data.snrL1[i];
3037 }
3038 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3039 {
3040 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3041 lli = '1';
3042 snr = '0'+Parser->Data.snrL2[i];
3043 }
3044 if(df & GNSSDF_L5DATA)
3045 {
3046 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3047 lli = '1';
3048 snr = ' ';
3049 }
3050 RTCM3Text("%14.3f%c%c",
3051 Parser->Data.measdata[i][pos],lli,snr);
3052 }
3053 else
3054 { /* no or illegal data */
3055 RTCM3Text(" ");
3056 }
3057 }
3058 }
3059 else if(sys[RTCM3_MSM_SBAS])
3060 {
3061 for(j = 0; j < Parser->info[RTCM3_MSM_SBAS].numtypes; ++j)
3062 {
3063 long long df = Parser->info[RTCM3_MSM_SBAS].flags[j];
3064 int pos = Parser->info[RTCM3_MSM_SBAS].pos[j];
3065 if((Parser->Data.dataflags[i] & df)
3066 && !isnan(Parser->Data.measdata[i][pos])
3067 && !isinf(Parser->Data.measdata[i][pos])
3068 && (Parser->Data.codetype[i][pos]
3069 && Parser->info[RTCM3_MSM_SBAS].type[pos]
3070 && Parser->info[RTCM3_MSM_SBAS].type[pos]
3071 == Parser->Data.codetype[i][pos][1]))
3072 {
3073 char lli = ' ';
3074 char snr = ' ';
3075 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3076 {
3077 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3078 lli = '1';
3079 snr = '0'+Parser->Data.snrL1[i];
3080 }
3081 if(df & GNSSDF_L5DATA)
3082 {
3083 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3084 lli = '1';
3085 snr = ' ';
3086 }
3087 RTCM3Text("%14.3f%c%c",
3088 Parser->Data.measdata[i][pos],lli,snr);
3089 }
3090 else
3091 { /* no or illegal data */
3092 RTCM3Text(" ");
3093 }
3094 }
3095 }
3096 else
3097 {
3098 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
3099 {
3100 long long df = Parser->info[RTCM3_MSM_GPS].flags[j];
3101 int pos = Parser->info[RTCM3_MSM_GPS].pos[j];
3102 if((Parser->Data.dataflags[i] & df)
3103 && !isnan(Parser->Data.measdata[i][pos])
3104 && !isinf(Parser->Data.measdata[i][pos])
3105 && (Parser->Data.codetype[i][pos]
3106 && Parser->info[RTCM3_MSM_GPS].type[pos]
3107 && Parser->info[RTCM3_MSM_GPS].type[pos]
3108 == Parser->Data.codetype[i][pos][1]))
3109 {
3110 char lli = ' ';
3111 char snr = ' ';
3112 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3113 {
3114 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3115 lli = '1';
3116 snr = '0'+Parser->Data.snrL1[i];
3117 }
3118 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3119 {
3120 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3121 lli = '1';
3122 snr = '0'+Parser->Data.snrL2[i];
3123 }
3124 if(df & GNSSDF_L5DATA)
3125 {
3126 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3127 lli = '1';
3128 snr = ' ';
3129 }
3130 RTCM3Text("%14.3f%c%c",
3131 Parser->Data.measdata[i][pos],lli,snr);
3132 }
3133 else
3134 { /* no or illegal data */
3135 RTCM3Text(" ");
3136 }
3137 }
3138 }
3139 RTCM3Text("\n");
3140 }
3141 }
3142 else
3143 {
3144 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f %d%3d",
3145 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
3146 + fmod(Parser->Data.timeofweek/1000.0,1.0), nh ? 4 : 0,
3147 Parser->Data.numsats);
3148 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
3149 {
3150 if(Parser->Data.satellites[i] <= PRN_GPS_END)
3151 RTCM3Text("G%02d", Parser->Data.satellites[i]);
3152 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
3153 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
3154 RTCM3Text("R%02d", Parser->Data.satellites[i]
3155 - (PRN_GLONASS_START-1));
3156 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3157 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3158 RTCM3Text("S%02d", Parser->Data.satellites[i]
3159 - PRN_SBAS_START+20);
3160 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3161 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3162 RTCM3Text("E%02d", Parser->Data.satellites[i]
3163 - (PRN_GALILEO_START-1));
3164 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3165 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3166 RTCM3Text("E%02d", Parser->Data.satellites[i]
3167 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3168 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3169 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3170 RTCM3Text("J%02d", Parser->Data.satellites[i]
3171 - (PRN_QZSS_START-1));
3172 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
3173 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
3174 RTCM3Text("C%02d", Parser->Data.satellites[i]
3175 - (PRN_COMPASS_START-1));
3176 else
3177 RTCM3Text("%3d", Parser->Data.satellites[i]);
3178 }
3179 RTCM3Text("\n");
3180 o = 12;
3181 j = Parser->Data.numsats - 12;
3182 while(j > 0)
3183 {
3184 RTCM3Text(" ");
3185 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
3186 {
3187 if(Parser->Data.satellites[i] <= PRN_GPS_END)
3188 RTCM3Text("G%02d", Parser->Data.satellites[i]);
3189 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
3190 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
3191 RTCM3Text("R%02d", Parser->Data.satellites[i]
3192 - (PRN_GLONASS_START-1));
3193 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3194 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3195 RTCM3Text("S%02d", Parser->Data.satellites[i]
3196 - PRN_SBAS_START+20);
3197 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3198 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3199 RTCM3Text("E%02d", Parser->Data.satellites[i]
3200 - (PRN_GALILEO_START-1));
3201 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3202 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3203 RTCM3Text("E%02d", Parser->Data.satellites[i]
3204 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3205 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3206 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3207 RTCM3Text("J%02d", Parser->Data.satellites[i]
3208 - (PRN_QZSS_START-1));
3209 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
3210 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
3211 RTCM3Text("C%02d", Parser->Data.satellites[i]
3212 - (PRN_COMPASS_START-1));
3213 else
3214 RTCM3Text("%3d", Parser->Data.satellites[i]);
3215 }
3216 RTCM3Text("\n");
3217 j -= 12;
3218 o += 12;
3219 }
3220 if(nh)
3221 {
3222 RTCM3Text("%s\n "
3223 " END OF HEADER\n", newheader);
3224 }
3225 for(i = 0; i < Parser->Data.numsats; ++i)
3226 {
3227 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
3228 {
3229 int v = 0;
3230 long long df = Parser->flags[j];
3231 int pos = Parser->pos[j];
3232 if((Parser->Data.dataflags[i] & df)
3233 && !isnan(Parser->Data.measdata[i][pos])
3234 && !isinf(Parser->Data.measdata[i][pos]))
3235 {
3236 v = 1;
3237 }
3238 else
3239 {
3240 df = Parser->info[RTCM3_MSM_GPS].flags[j];
3241 pos = Parser->info[RTCM3_MSM_GPS].pos[j];
3242
3243 if((Parser->Data.dataflags[i] & df)
3244 && !isnan(Parser->Data.measdata[i][pos])
3245 && !isinf(Parser->Data.measdata[i][pos]))
3246 {
3247 v = 1;
3248 }
3249 }
3250
3251 if(!v)
3252 { /* no or illegal data */
3253 RTCM3Text(" ");
3254 }
3255 else
3256 {
3257 char lli = ' ';
3258 char snr = ' ';
3259 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3260 {
3261 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3262 lli = '1';
3263 snr = '0'+Parser->Data.snrL1[i];
3264 }
3265 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3266 {
3267 if(Parser->Data.dataflags2[i]
3268 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
3269 {
3270 lli = '0';
3271 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3272 lli += 1;
3273 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
3274 lli += 4;
3275 }
3276 snr = '0'+Parser->Data.snrL2[i];
3277 }
3278 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
3279 & GNSSDF2_XCORRL2))
3280 lli = '4';
3281 RTCM3Text("%14.3f%c%c",
3282 Parser->Data.measdata[i][pos],lli,snr);
3283 }
3284 if(j%5 == 4 || j == Parser->info[RTCM3_MSM_GPS].numtypes-1)
3285 RTCM3Text("\n");
3286 }
3287 }
3288 }
3289 }
3290 }
3291 }
3292}
3293
3294#ifndef NO_RTCM3_MAIN
3295static char datestr[] = "$Date: 2015-01-05 14:52:38 +0000 (Mon, 05 Jan 2015) $";
3296
3297/* The string, which is send as agent in HTTP request */
3298#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
3299
3300#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
3301
3302static const char encodingTable [64] = {
3303 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
3304 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
3305 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
3306 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
3307};
3308
3309/* does not buffer overrun, but breaks directly after an error */
3310/* returns the number of required bytes */
3311static int encode(char *buf, int size, const char *user, const char *pwd)
3312{
3313 unsigned char inbuf[3];
3314 char *out = buf;
3315 int i, sep = 0, fill = 0, bytes = 0;
3316
3317 while(*user || *pwd)
3318 {
3319 i = 0;
3320 while(i < 3 && *user) inbuf[i++] = *(user++);
3321 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
3322 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
3323 while(i < 3) {inbuf[i++] = 0; ++fill; }
3324 if(out-buf < size-1)
3325 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
3326 if(out-buf < size-1)
3327 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
3328 | ((inbuf [1] & 0xF0) >> 4)];
3329 if(out-buf < size-1)
3330 {
3331 if(fill == 2)
3332 *(out++) = '=';
3333 else
3334 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
3335 | ((inbuf [2] & 0xC0) >> 6)];
3336 }
3337 if(out-buf < size-1)
3338 {
3339 if(fill >= 1)
3340 *(out++) = '=';
3341 else
3342 *(out++) = encodingTable[inbuf [2] & 0x3F];
3343 }
3344 bytes += 4;
3345 }
3346 if(out-buf < size)
3347 *out = 0;
3348 return bytes;
3349}
3350
3351static int stop = 0;
3352
3353struct Args
3354{
3355 const char *server;
3356 const char *port;
3357 int mode;
3358 int timeout;
3359 int rinex3;
3360 int changeobs;
3361 const char *user;
3362 const char *password;
3363 const char *proxyhost;
3364 const char *proxyport;
3365 const char *nmea;
3366 const char *data;
3367 const char *headerfile;
3368 const char *sbasephemeris;
3369 const char *gpsephemeris;
3370 const char *qzssephemeris;
3371 const char *glonassephemeris;
3372};
3373
3374/* option parsing */
3375#ifdef NO_LONG_OPTS
3376#define LONG_OPT(a)
3377#else
3378#define LONG_OPT(a) a
3379static struct option opts[] = {
3380{ "data", required_argument, 0, 'd'},
3381{ "server", required_argument, 0, 's'},
3382{ "password", required_argument, 0, 'p'},
3383{ "port", required_argument, 0, 'r'},
3384{ "timeout", required_argument, 0, 't'},
3385{ "header", required_argument, 0, 'f'},
3386{ "user", required_argument, 0, 'u'},
3387{ "gpsephemeris", required_argument, 0, 'E'},
3388{ "qzssephemeris", required_argument, 0, 'Q'},
3389{ "glonassephemeris", required_argument, 0, 'G'},
3390{ "sbasephemeris", required_argument, 0, 'B'},
3391{ "rinex3", no_argument, 0, '3'},
3392{ "changeobs", no_argument, 0, 'O'},
3393{ "proxyport", required_argument, 0, 'R'},
3394{ "proxyhost", required_argument, 0, 'S'},
3395{ "nmea", required_argument, 0, 'n'},
3396{ "mode", required_argument, 0, 'M'},
3397{ "help", no_argument, 0, 'h'},
3398{0,0,0,0}};
3399#endif
3400#define ARGOPT "-d:s:p:r:t:f:u:E:G:B:Q:M:S:R:n:h3O"
3401
3402enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
3403
3404static const char *geturl(const char *url, struct Args *args)
3405{
3406 static char buf[1000];
3407 static char *Buffer = buf;
3408 static char *Bufend = buf+sizeof(buf);
3409
3410 if(strncmp("ntrip:", url, 6))
3411 return "URL must start with 'ntrip:'.";
3412 url += 6; /* skip ntrip: */
3413
3414 if(*url != '@' && *url != '/')
3415 {
3416 /* scan for mountpoint */
3417 args->data = Buffer;
3418 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
3419 *(Buffer++) = *(url++);
3420 if(Buffer == args->data)
3421 return "Mountpoint required.";
3422 else if(Buffer >= Bufend-1)
3423 return "Parsing buffer too short.";
3424 *(Buffer++) = 0;
3425 }
3426
3427 if(*url == '/') /* username and password */
3428 {
3429 ++url;
3430 args->user = Buffer;
3431 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
3432 *(Buffer++) = *(url++);
3433 if(Buffer == args->user)
3434 return "Username cannot be empty.";
3435 else if(Buffer >= Bufend-1)
3436 return "Parsing buffer too short.";
3437 *(Buffer++) = 0;
3438
3439 if(*url == ':') ++url;
3440
3441 args->password = Buffer;
3442 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3443 *(Buffer++) = *(url++);
3444 if(Buffer == args->password)
3445 return "Password cannot be empty.";
3446 else if(Buffer >= Bufend-1)
3447 return "Parsing buffer too short.";
3448 *(Buffer++) = 0;
3449 }
3450
3451 if(*url == '@') /* server */
3452 {
3453 ++url;
3454 if(*url != '@' && *url != ':')
3455 {
3456 args->server = Buffer;
3457 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
3458 *(Buffer++) = *(url++);
3459 if(Buffer == args->server)
3460 return "Servername cannot be empty.";
3461 else if(Buffer >= Bufend-1)
3462 return "Parsing buffer too short.";
3463 *(Buffer++) = 0;
3464 }
3465
3466 if(*url == ':')
3467 {
3468 ++url;
3469 args->port = Buffer;
3470 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3471 *(Buffer++) = *(url++);
3472 if(Buffer == args->port)
3473 return "Port cannot be empty.";
3474 else if(Buffer >= Bufend-1)
3475 return "Parsing buffer too short.";
3476 *(Buffer++) = 0;
3477 }
3478
3479 if(*url == '@') /* proxy */
3480 {
3481 ++url;
3482 args->proxyhost = Buffer;
3483 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
3484 *(Buffer++) = *(url++);
3485 if(Buffer == args->proxyhost)
3486 return "Proxy servername cannot be empty.";
3487 else if(Buffer >= Bufend-1)
3488 return "Parsing buffer too short.";
3489 *(Buffer++) = 0;
3490
3491 if(*url == ':')
3492 {
3493 ++url;
3494 args->proxyport = Buffer;
3495 while(*url && *url != ';' && Buffer != Bufend)
3496 *(Buffer++) = *(url++);
3497 if(Buffer == args->proxyport)
3498 return "Proxy port cannot be empty.";
3499 else if(Buffer >= Bufend-1)
3500 return "Parsing buffer too short.";
3501 *(Buffer++) = 0;
3502 }
3503 }
3504 }
3505 if(*url == ';') /* NMEA */
3506 {
3507 args->nmea = ++url;
3508 while(*url)
3509 ++url;
3510 }
3511
3512 return *url ? "Garbage at end of server string." : 0;
3513}
3514
3515static int getargs(int argc, char **argv, struct Args *args)
3516{
3517 int res = 1;
3518 int getoptr;
3519 int help = 0;
3520 char *t;
3521
3522 args->server = "www.euref-ip.net";
3523 args->port = "2101";
3524 args->timeout = 60;
3525 args->user = "";
3526 args->password = "";
3527 args->data = 0;
3528 args->headerfile = 0;
3529 args->gpsephemeris = 0;
3530 args->qzssephemeris = 0;
3531 args->sbasephemeris = 0;
3532 args->glonassephemeris = 0;
3533 args->rinex3 = 0;
3534 args->nmea = 0;
3535 args->changeobs = 0;
3536 args->proxyhost = 0;
3537 args->proxyport = "2101";
3538 args->mode = AUTO;
3539 help = 0;
3540
3541 do
3542 {
3543
3544#ifdef NO_LONG_OPTS
3545 switch((getoptr = getopt(argc, argv, ARGOPT)))
3546#else
3547 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
3548#endif
3549 {
3550 case 's': args->server = optarg; break;
3551 case 'u': args->user = optarg; break;
3552 case 'p': args->password = optarg; break;
3553 case 'd': args->data = optarg; break;
3554 case 'f': args->headerfile = optarg; break;
3555 case 'E': args->gpsephemeris = optarg; break;
3556 case 'B': args->sbasephemeris = optarg; break;
3557 case 'G': args->glonassephemeris = optarg; break;
3558 case 'Q': args->qzssephemeris = optarg; break;
3559 case 'r': args->port = optarg; break;
3560 case '3': args->rinex3 = 1; break;
3561 case 'S': args->proxyhost = optarg; break;
3562 case 'n': args->nmea = optarg; break;
3563 case 'R': args->proxyport = optarg; break;
3564 case 'O': args->changeobs = 1; break;
3565 case 'h': help=1; break;
3566 case 'M':
3567 args->mode = 0;
3568 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
3569 args->mode = NTRIP1;
3570 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
3571 args->mode = HTTP;
3572 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
3573 args->mode = RTSP;
3574 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
3575 args->mode = AUTO;
3576 else args->mode = atoi(optarg);
3577 if((args->mode == 0) || (args->mode >= END))
3578 {
3579 fprintf(stderr, "Mode %s unknown\n", optarg);
3580 res = 0;
3581 }
3582 break;
3583 case 't':
3584 args->timeout = strtoul(optarg, &t, 10);
3585 if((t && *t) || args->timeout < 0)
3586 res = 0;
3587 break;
3588
3589 case 1:
3590 {
3591 const char *err;
3592 if((err = geturl(optarg, args)))
3593 {
3594 RTCM3Error("%s\n\n", err);
3595 res = 0;
3596 }
3597 }
3598 break;
3599 case -1: break;
3600 }
3601 } while(getoptr != -1 || !res);
3602
3603 datestr[0] = datestr[7];
3604 datestr[1] = datestr[8];
3605 datestr[2] = datestr[9];
3606 datestr[3] = datestr[10];
3607 datestr[5] = datestr[12];
3608 datestr[6] = datestr[13];
3609 datestr[8] = datestr[15];
3610 datestr[9] = datestr[16];
3611 datestr[4] = datestr[7] = '-';
3612 datestr[10] = 0;
3613
3614 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
3615 {
3616 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
3617 "Please specify only one navigation file.\n");
3618 res = 0;
3619 }
3620 else if(!res || help)
3621 {
3622 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
3623 "\nUsage: %s -s server -u user ...\n"
3624 " -d " LONG_OPT("--data ") "the requested data set\n"
3625 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
3626 " -s " LONG_OPT("--server ") "the server name or address\n"
3627 " -p " LONG_OPT("--password ") "the login password\n"
3628 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
3629 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
3630 " -u " LONG_OPT("--user ") "the user name\n"
3631 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
3632 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
3633 " -Q " LONG_OPT("--qzssephemeris ") "output file for QZSS ephemeris data\n"
3634 " -B " LONG_OPT("--sbasephemeris ") "output file for SBAS ephemeris data\n"
3635 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
3636 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
3637 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
3638 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
3639 " -O " LONG_OPT("--changeobs ") "Add observation type change header lines\n"
3640 " -M " LONG_OPT("--mode ") "mode for data request\n"
3641 " Valid modes are:\n"
3642 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
3643 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
3644 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
3645 " 4, a, auto automatic detection (default)\n"
3646 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
3647 , revisionstr, datestr, argv[0], argv[0]);
3648 exit(1);
3649 }
3650 return res;
3651}
3652
3653/* let the output complete a block if necessary */
3654static void signalhandler(int sig)
3655{
3656 if(!stop)
3657 {
3658 RTCM3Error("Stop signal number %d received. "
3659 "Trying to terminate gentle.\n", sig);
3660 stop = 1;
3661 alarm(1);
3662 }
3663}
3664
3665#ifndef WINDOWSVERSION
3666static void WaitMicro(int mic)
3667{
3668 struct timeval tv;
3669 tv.tv_sec = mic/1000000;
3670 tv.tv_usec = mic%1000000;
3671#ifdef DEBUG
3672 fprintf(stderr, "Waiting %d micro seconds\n", mic);
3673#endif
3674 select(0, 0, 0, 0, &tv);
3675}
3676#else /* WINDOWSVERSION */
3677void WaitMicro(int mic)
3678{
3679 Sleep(mic/1000);
3680}
3681#endif /* WINDOWSVERSION */
3682
3683#define ALARMTIME (2*60)
3684
3685/* for some reason we had to abort hard (maybe waiting for data */
3686#ifdef __GNUC__
3687static __attribute__ ((noreturn)) void signalhandler_alarm(
3688int sig __attribute__((__unused__)))
3689#else /* __GNUC__ */
3690static void signalhandler_alarm(int sig)
3691#endif /* __GNUC__ */
3692{
3693 RTCM3Error("Programm forcefully terminated.\n");
3694 exit(1);
3695}
3696
3697int main(int argc, char **argv)
3698{
3699 struct Args args;
3700 struct RTCM3ParserData Parser;
3701
3702 setbuf(stdout, 0);
3703 setbuf(stdin, 0);
3704 setbuf(stderr, 0);
3705
3706 fixrevision();
3707
3708 signal(SIGINT, signalhandler);
3709 signal(SIGALRM,signalhandler_alarm);
3710 signal(SIGQUIT,signalhandler);
3711 signal(SIGTERM,signalhandler);
3712 signal(SIGPIPE,signalhandler);
3713 memset(&Parser, 0, sizeof(Parser));
3714 {
3715 time_t tim;
3716 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
3717 Parser.GPSWeek = tim/(7*24*60*60);
3718 Parser.GPSTOW = tim%(7*24*60*60);
3719 }
3720
3721 if(getargs(argc, argv, &args))
3722 {
3723 int sockfd, numbytes;
3724 char buf[MAXDATASIZE];
3725 struct sockaddr_in their_addr; /* connector's address information */
3726 struct hostent *he;
3727 struct servent *se;
3728 const char *server, *port, *proxyserver = 0;
3729 char proxyport[6];
3730 char *b;
3731 long i;
3732 struct timeval tv;
3733
3734 alarm(ALARMTIME);
3735
3736 Parser.headerfile = args.headerfile;
3737 Parser.glonassephemeris = args.glonassephemeris;
3738 Parser.gpsephemeris = args.gpsephemeris;
3739 Parser.qzssephemeris = args.qzssephemeris;
3740 Parser.sbasephemeris = args.sbasephemeris;
3741 Parser.rinex3 = args.rinex3;
3742 Parser.changeobs = args.changeobs;
3743
3744 if(args.proxyhost)
3745 {
3746 int p;
3747 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
3748 p = i;
3749 else if(!(se = getservbyname(args.port, 0)))
3750 {
3751 RTCM3Error("Can't resolve port %s.", args.port);
3752 exit(1);
3753 }
3754 else
3755 {
3756 p = ntohs(se->s_port);
3757 }
3758 snprintf(proxyport, sizeof(proxyport), "%d", p);
3759 port = args.proxyport;
3760 proxyserver = args.server;
3761 server = args.proxyhost;
3762 }
3763 else
3764 {
3765 server = args.server;
3766 port = args.port;
3767 }
3768
3769 memset(&their_addr, 0, sizeof(struct sockaddr_in));
3770 if((i = strtol(port, &b, 10)) && (!b || !*b))
3771 their_addr.sin_port = htons(i);
3772 else if(!(se = getservbyname(port, 0)))
3773 {
3774 RTCM3Error("Can't resolve port %s.", port);
3775 exit(1);
3776 }
3777 else
3778 {
3779 their_addr.sin_port = se->s_port;
3780 }
3781 if(!(he=gethostbyname(server)))
3782 {
3783 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3784 exit(1);
3785 }
3786 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3787 {
3788 perror("socket");
3789 exit(1);
3790 }
3791
3792 tv.tv_sec = args.timeout;
3793 tv.tv_usec = 0;
3794 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3795 {
3796 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3797 exit(1);
3798 }
3799
3800 their_addr.sin_family = AF_INET;
3801 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3802
3803 if(args.data && args.mode == RTSP)
3804 {
3805 struct sockaddr_in local;
3806 int sockudp, localport;
3807 int cseq = 1;
3808 socklen_t len;
3809
3810 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3811 {
3812 perror("socket");
3813 exit(1);
3814 }
3815 /* fill structure with local address information for UDP */
3816 memset(&local, 0, sizeof(local));
3817 local.sin_family = AF_INET;
3818 local.sin_port = htons(0);
3819 local.sin_addr.s_addr = htonl(INADDR_ANY);
3820 len = sizeof(local);
3821 /* bind() in order to get a random RTP client_port */
3822 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3823 {
3824 perror("bind");
3825 exit(1);
3826 }
3827 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3828 {
3829 localport = ntohs(local.sin_port);
3830 }
3831 else
3832 {
3833 perror("local access failed");
3834 exit(1);
3835 }
3836 if(connect(sockfd, (struct sockaddr *)&their_addr,
3837 sizeof(struct sockaddr)) == -1)
3838 {
3839 perror("connect");
3840 exit(1);
3841 }
3842 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3843 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3844 "CSeq: %d\r\n"
3845 "Ntrip-Version: Ntrip/2.0\r\n"
3846 "Ntrip-Component: Ntripclient\r\n"
3847 "User-Agent: %s/%s\r\n"
3848 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3849 "Authorization: Basic ",
3850 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3851 args.data, cseq++, AGENTSTRING, revisionstr, localport);
3852 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3853 {
3854 RTCM3Error("Requested data too long\n");
3855 exit(1);
3856 }
3857 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3858 if(i > MAXDATASIZE-4)
3859 {
3860 RTCM3Error("Username and/or password too long\n");
3861 exit(1);
3862 }
3863 buf[i++] = '\r';
3864 buf[i++] = '\n';
3865 buf[i++] = '\r';
3866 buf[i++] = '\n';
3867 if(args.nmea)
3868 {
3869 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3870 if(j >= 0 && j < MAXDATASIZE-i)
3871 i += j;
3872 else
3873 {
3874 RTCM3Error("NMEA string too long\n");
3875 exit(1);
3876 }
3877 }
3878 if(send(sockfd, buf, (size_t)i, 0) != i)
3879 {
3880 perror("send");
3881 exit(1);
3882 }
3883 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3884 {
3885 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3886 {
3887 int serverport = 0, session = 0;
3888 const char *portcheck = "server_port=";
3889 const char *sessioncheck = "session: ";
3890 int l = strlen(portcheck)-1;
3891 int j=0;
3892 for(i = 0; j != l && i < numbytes-l; ++i)
3893 {
3894 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3895 ;
3896 }
3897 if(i == numbytes-l)
3898 {
3899 RTCM3Error("No server port number found\n");
3900 exit(1);
3901 }
3902 else
3903 {
3904 i+=l;
3905 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3906 serverport = serverport * 10 + buf[i++]-'0';
3907 if(buf[i] != '\r' && buf[i] != ';')
3908 {
3909 RTCM3Error("Could not extract server port\n");
3910 exit(1);
3911 }
3912 }
3913 l = strlen(sessioncheck)-1;
3914 j=0;
3915 for(i = 0; j != l && i < numbytes-l; ++i)
3916 {
3917 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3918 ;
3919 }
3920 if(i == numbytes-l)
3921 {
3922 RTCM3Error("No session number found\n");
3923 exit(1);
3924 }
3925 else
3926 {
3927 i+=l;
3928 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3929 session = session * 10 + buf[i++]-'0';
3930 if(buf[i] != '\r')
3931 {
3932 RTCM3Error("Could not extract session number\n");
3933 exit(1);
3934 }
3935 }
3936
3937 i = snprintf(buf, MAXDATASIZE,
3938 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3939 "CSeq: %d\r\n"
3940 "Session: %d\r\n"
3941 "\r\n",
3942 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3943 args.data, cseq++, session);
3944
3945 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3946 {
3947 RTCM3Error("Requested data too long\n");
3948 exit(1);
3949 }
3950 if(send(sockfd, buf, (size_t)i, 0) != i)
3951 {
3952 perror("send");
3953 exit(1);
3954 }
3955 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3956 {
3957 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3958 {
3959 struct sockaddr_in addrRTP;
3960 /* fill structure with caster address information for UDP */
3961 memset(&addrRTP, 0, sizeof(addrRTP));
3962 addrRTP.sin_family = AF_INET;
3963 addrRTP.sin_port = htons(serverport);
3964 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3965 len = sizeof(addrRTP);
3966 int ts = 0;
3967 int sn = 0;
3968 int ssrc = 0;
3969 int init = 0;
3970 int u, v, w;
3971 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3972 (struct sockaddr*) &addrRTP, &len)) > 0)
3973 {
3974 alarm(ALARMTIME);
3975 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3976 {
3977 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3978 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3979 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3980 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3981 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3982
3983 if(init)
3984 {
3985 int z;
3986 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3987 if(ssrc != w || ts > v)
3988 {
3989 RTCM3Error("Illegal UDP data received.\n");
3990 exit(1);
3991 }
3992 if(u > sn) /* don't show out-of-order packets */
3993 for(z = 12; z < i && !stop; ++z)
3994 HandleByte(&Parser, (unsigned int) buf[z]);
3995 }
3996 sn = u; ts = v; ssrc = w; init = 1;
3997 }
3998 else
3999 {
4000 RTCM3Error("Illegal UDP header.\n");
4001 exit(1);
4002 }
4003 }
4004 }
4005 i = snprintf(buf, MAXDATASIZE,
4006 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
4007 "CSeq: %d\r\n"
4008 "Session: %d\r\n"
4009 "\r\n",
4010 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
4011 args.data, cseq++, session);
4012
4013 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
4014 {
4015 RTCM3Error("Requested data too long\n");
4016 exit(1);
4017 }
4018 if(send(sockfd, buf, (size_t)i, 0) != i)
4019 {
4020 perror("send");
4021 exit(1);
4022 }
4023 }
4024 else
4025 {
4026 RTCM3Error("Could not start data stream.\n");
4027 exit(1);
4028 }
4029 }
4030 else
4031 {
4032 RTCM3Error("Could not setup initial control connection.\n");
4033 exit(1);
4034 }
4035 }
4036 else
4037 {
4038 perror("recv");
4039 exit(1);
4040 }
4041 }
4042 else
4043 {
4044 if(connect(sockfd, (struct sockaddr *)&their_addr,
4045 sizeof(struct sockaddr)) == -1)
4046 {
4047 perror("connect");
4048 exit(1);
4049 }
4050 if(!args.data)
4051 {
4052 i = snprintf(buf, MAXDATASIZE,
4053 "GET %s%s%s%s/ HTTP/1.0\r\n"
4054 "Host: %s\r\n%s"
4055 "User-Agent: %s/%s\r\n"
4056 "Connection: close\r\n"
4057 "\r\n"
4058 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
4059 proxyserver ? ":" : "", proxyserver ? proxyport : "",
4060 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
4061 AGENTSTRING, revisionstr);
4062 }
4063 else
4064 {
4065 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
4066 "GET %s%s%s%s/%s HTTP/1.0\r\n"
4067 "Host: %s\r\n%s"
4068 "User-Agent: %s/%s\r\n"
4069 "Connection: close\r\n"
4070 "Authorization: Basic "
4071 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
4072 proxyserver ? ":" : "", proxyserver ? proxyport : "",
4073 args.data, args.server,
4074 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
4075 AGENTSTRING, revisionstr);
4076 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
4077 {
4078 RTCM3Error("Requested data too long\n");
4079 exit(1);
4080 }
4081 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
4082 if(i > MAXDATASIZE-4)
4083 {
4084 RTCM3Error("Username and/or password too long\n");
4085 exit(1);
4086 }
4087 buf[i++] = '\r';
4088 buf[i++] = '\n';
4089 buf[i++] = '\r';
4090 buf[i++] = '\n';
4091 if(args.nmea)
4092 {
4093 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
4094 if(j >= 0 && j < MAXDATASIZE-i)
4095 i += j;
4096 else
4097 {
4098 RTCM3Error("NMEA string too long\n");
4099 exit(1);
4100 }
4101 }
4102 }
4103 if(send(sockfd, buf, (size_t)i, 0) != i)
4104 {
4105 perror("send");
4106 exit(1);
4107 }
4108 if(args.data)
4109 {
4110 int k = 0;
4111 int chunkymode = 0;
4112 int totalbytes = 0;
4113 int chunksize = 0;
4114
4115 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
4116 {
4117 if(numbytes > 0)
4118 alarm(ALARMTIME);
4119 else
4120 {
4121 WaitMicro(100);
4122 continue;
4123 }
4124 if(!k)
4125 {
4126 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
4127 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
4128 {
4129 const char *datacheck = "Content-Type: gnss/data\r\n";
4130 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
4131 int l = strlen(datacheck)-1;
4132 int j=0;
4133 for(i = 0; j != l && i < numbytes-l; ++i)
4134 {
4135 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
4136 ;
4137 }
4138 if(i == numbytes-l)
4139 {
4140 RTCM3Error("No 'Content-Type: gnss/data' found\n");
4141 exit(1);
4142 }
4143 l = strlen(chunkycheck)-1;
4144 j=0;
4145 for(i = 0; j != l && i < numbytes-l; ++i)
4146 {
4147 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
4148 ;
4149 }
4150 if(i < numbytes-l)
4151 chunkymode = 1;
4152 }
4153 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
4154 {
4155 RTCM3Error("Could not get the requested data: ");
4156 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
4157 {
4158 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
4159 }
4160 RTCM3Error("\n");
4161 exit(1);
4162 }
4163 else if(args.mode != NTRIP1)
4164 {
4165 if(args.mode != AUTO)
4166 {
4167 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
4168 args.mode == AUTO ? ", falling back to NTRIP1" : "");
4169 }
4170 if(args.mode == HTTP)
4171 exit(1);
4172 }
4173 ++k;
4174 }
4175 else
4176 {
4177 if(chunkymode)
4178 {
4179 int stop = 0;
4180 int pos = 0;
4181 while(!stop && pos < numbytes)
4182 {
4183 switch(chunkymode)
4184 {
4185 case 1: /* reading number starts */
4186 chunksize = 0;
4187 ++chunkymode; /* no break */
4188 case 2: /* during reading number */
4189 i = buf[pos++];
4190 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
4191 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
4192 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
4193 else if(i == '\r') ++chunkymode;
4194 else if(i == ';') chunkymode = 5;
4195 else stop = 1;
4196 break;
4197 case 3: /* scanning for return */
4198 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
4199 else stop = 1;
4200 break;
4201 case 4: /* output data */
4202 i = numbytes-pos;
4203 if(i > chunksize) i = chunksize;
4204 {
4205 int z;
4206 for(z = 0; z < i && !stop; ++z)
4207 HandleByte(&Parser, (unsigned int) buf[pos+z]);
4208 }
4209 totalbytes += i;
4210 chunksize -= i;
4211 pos += i;
4212 if(!chunksize)
4213 chunkymode = 1;
4214 break;
4215 case 5:
4216 if(i == '\r') chunkymode = 3;
4217 break;
4218 }
4219 }
4220 if(stop)
4221 {
4222 RTCM3Error("Error in chunky transfer encoding\n");
4223 break;
4224 }
4225 }
4226 else
4227 {
4228 totalbytes += numbytes;
4229 {
4230 int z;
4231 for(z = 0; z < numbytes && !stop; ++z)
4232 HandleByte(&Parser, (unsigned int) buf[z]);
4233 }
4234 }
4235 if(totalbytes < 0) /* overflow */
4236 {
4237 totalbytes = 0;
4238 }
4239 }
4240 }
4241 }
4242 else
4243 {
4244 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
4245 {
4246 alarm(ALARMTIME);
4247 fwrite(buf, (size_t)numbytes, 1, stdout);
4248 }
4249 }
4250 close(sockfd);
4251 }
4252 }
4253 return 0;
4254}
4255#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.