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

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

fix compiler warning

  • Property svn:keywords set to Id Revision Date
File size: 140.9 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 6552 2015-01-19 10:22:54Z 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: 6552 $";
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 if(rinex3)
1913 {
1914 return 1+snprintf(buffer, buffersize,
1915 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1916 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1917 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1918 }
1919 else
1920 {
1921 return 1+snprintf(buffer, buffersize,
1922 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
1923 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1924 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min);
1925 }
1926}
1927
1928#ifdef NO_RTCM3_MAIN
1929#define NUMSTARTSKIP 1
1930#else
1931#define NUMSTARTSKIP 3
1932#endif
1933
1934int HandleObsHeader(struct RTCM3ParserData *Parser, char *buffer,
1935size_t buffersize, struct HeaderData *hdata)
1936{
1937 int buffersizeold = buffersize;
1938 int i, modified = 0;
1939
1940 if(Parser->rinex3)
1941 {
1942 int flags;
1943#define CHECKFLAGSNEW(a, b, c) \
1944 if(flags & GNSSDF_##b##DATA) \
1945 { \
1946 int new = hdata ? 1 : 0; \
1947 if(!hdata) /* check if already known */ \
1948 { \
1949 int ic; \
1950 for(ic = 0; ic < Parser->info[RTCM3_MSM_##a].numtypes \
1951 && Parser->info[RTCM3_MSM_##a].flags[ic] != GNSSDF_##b##DATA; ++ic) \
1952 ; \
1953 if(ic == Parser->info[RTCM3_MSM_##a].numtypes) \
1954 new = 1; \
1955 } \
1956 if(new) \
1957 { \
1958 Parser->info[RTCM3_MSM_##a].flags[Parser->info[RTCM3_MSM_##a].numtypes] \
1959 = GNSSDF_##b##DATA; \
1960 Parser->info[RTCM3_MSM_##a].pos[Parser->info[RTCM3_MSM_##a].numtypes] \
1961 = GNSSENTRY_##b##DATA; \
1962 if(Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]) \
1963 { \
1964 snprintf(Parser->fieldbuffer##a+4*Parser->info[RTCM3_MSM_##a].numtypes, \
1965 sizeof(Parser->fieldbuffer##a)-4*Parser->info[RTCM3_MSM_##a].numtypes, \
1966 " %-2.2s%c", #c, Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]); \
1967 } \
1968 else \
1969 { \
1970 snprintf(Parser->fieldbuffer##a+4*Parser->info[RTCM3_MSM_##a].numtypes, \
1971 sizeof(Parser->fieldbuffer##a)-4*Parser->info[RTCM3_MSM_##a].numtypes, \
1972 " %-3s", #c); \
1973 } \
1974 ++Parser->info[RTCM3_MSM_##a].numtypes; \
1975 ++modified; \
1976 } \
1977 }
1978
1979#define INITFLAGS(a) \
1980 flags = Parser->startflags; \
1981 modified = 0; \
1982 for(i = 0; i < Parser->Data.numsats; ++i) \
1983 { \
1984 if(Parser->Data.satellites[i] >= PRN_##a##_START \
1985 && Parser->Data.satellites[i] <= PRN_##a##_END) \
1986 flags |= Parser->Data.dataflags[i]; \
1987 }
1988
1989 INITFLAGS(SBAS)
1990 CHECKFLAGSNEW(SBAS, C1, C1C)
1991 CHECKFLAGSNEW(SBAS, L1C, L1C)
1992 CHECKFLAGSNEW(SBAS, D1C, D1C)
1993 CHECKFLAGSNEW(SBAS, S1C, S1C)
1994 CHECKFLAGSNEW(SBAS, C5, C5)
1995 CHECKFLAGSNEW(SBAS, L5, L5)
1996 CHECKFLAGSNEW(SBAS, D5, D5)
1997 CHECKFLAGSNEW(SBAS, S5, S5)
1998
1999 if(modified)
2000 {
2001 if(hdata)
2002 hdata->data.named.typesofobsS = buffer;
2003 i = 1+snprintf(buffer, buffersize,
2004 "S %3d%-52.52s SYS / # / OBS TYPES",
2005 Parser->info[RTCM3_MSM_SBAS].numtypes, Parser->fieldbufferSBAS);
2006 buffer += i; buffersize -= i;
2007 }
2008
2009 INITFLAGS(GPS)
2010 CHECKFLAGSNEW(GPS, C1, C1C)
2011 CHECKFLAGSNEW(GPS, L1C, L1C)
2012 CHECKFLAGSNEW(GPS, D1C, D1C)
2013 CHECKFLAGSNEW(GPS, S1C, S1C)
2014 CHECKFLAGSNEW(GPS, P1, C1W)
2015 CHECKFLAGSNEW(GPS, L1P, L1W)
2016 CHECKFLAGSNEW(GPS, D1P, D1W)
2017 CHECKFLAGSNEW(GPS, S1P, S1W)
2018 CHECKFLAGSNEW(GPS, C5, C5)
2019 CHECKFLAGSNEW(GPS, L5, L5)
2020 CHECKFLAGSNEW(GPS, D5, D5)
2021 CHECKFLAGSNEW(GPS, S5, S5)
2022 CHECKFLAGSNEW(GPS, P2, C2W)
2023 CHECKFLAGSNEW(GPS, L2P, L2W)
2024 CHECKFLAGSNEW(GPS, D2P, D2W)
2025 CHECKFLAGSNEW(GPS, S2P, S2W)
2026 CHECKFLAGSNEW(GPS, C2, C2)
2027 CHECKFLAGSNEW(GPS, L2C, L2)
2028 CHECKFLAGSNEW(GPS, D2C, D2)
2029 CHECKFLAGSNEW(GPS, S2C, S2)
2030 CHECKFLAGSNEW(GPS, C1N, C1)
2031 CHECKFLAGSNEW(GPS, L1N, L1)
2032 CHECKFLAGSNEW(GPS, D1N, D1)
2033 CHECKFLAGSNEW(GPS, S1N, S1)
2034
2035 if(modified)
2036 {
2037 if(hdata)
2038 hdata->data.named.typesofobsG = buffer;
2039 i = 1+snprintf(buffer, buffersize,
2040 "G %3d%-52.52s SYS / # / OBS TYPES",
2041 Parser->info[RTCM3_MSM_GPS].numtypes, Parser->fieldbufferGPS);
2042 if(Parser->info[RTCM3_MSM_GPS].numtypes>13)
2043 {
2044 i += snprintf(buffer+i-1, buffersize,
2045 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGPS+13*4);
2046 }
2047 buffer += i; buffersize -= i;
2048 }
2049
2050 INITFLAGS(GLONASS)
2051 CHECKFLAGSNEW(GLONASS, C1, C1C)
2052 CHECKFLAGSNEW(GLONASS, L1C, L1C)
2053 CHECKFLAGSNEW(GLONASS, D1C, D1C)
2054 CHECKFLAGSNEW(GLONASS, S1C, S1C)
2055 CHECKFLAGSNEW(GLONASS, P1, C1P)
2056 CHECKFLAGSNEW(GLONASS, L1P, L1P)
2057 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2058 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2059 CHECKFLAGSNEW(GLONASS, P2, C2P)
2060 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2061 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2062 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2063 CHECKFLAGSNEW(GLONASS, C2, C2C)
2064 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2065 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2066 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2067
2068 if(modified)
2069 {
2070 if(hdata)
2071 hdata->data.named.typesofobsR = buffer;
2072 i = 1+snprintf(buffer, buffersize,
2073 "R %3d%-52.52s SYS / # / OBS TYPES",
2074 Parser->info[RTCM3_MSM_GLONASS].numtypes, Parser->fieldbufferGLONASS);
2075 if(Parser->info[RTCM3_MSM_GLONASS].numtypes>13)
2076 {
2077 i += snprintf(buffer+i-1, buffersize,
2078 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGLONASS+13*4);
2079 }
2080 buffer += i; buffersize -= i;
2081 }
2082
2083 INITFLAGS(GALGIO)
2084 CHECKFLAGSNEW(GALILEO, C1, C1)
2085 CHECKFLAGSNEW(GALILEO, L1C, L1)
2086 CHECKFLAGSNEW(GALILEO, D1C, D1)
2087 CHECKFLAGSNEW(GALILEO, S1C, S1)
2088 CHECKFLAGSNEW(GALILEO, C6, C6)
2089 CHECKFLAGSNEW(GALILEO, L6, L6)
2090 CHECKFLAGSNEW(GALILEO, D6, D6)
2091 CHECKFLAGSNEW(GALILEO, S6, S6)
2092 CHECKFLAGSNEW(GALILEO, C5, C5)
2093 CHECKFLAGSNEW(GALILEO, L5, L5)
2094 CHECKFLAGSNEW(GALILEO, D5, D5)
2095 CHECKFLAGSNEW(GALILEO, S5, S5)
2096 CHECKFLAGSNEW(GALILEO, C5B, C7)
2097 CHECKFLAGSNEW(GALILEO, L5B, L7)
2098 CHECKFLAGSNEW(GALILEO, D5B, D7)
2099 CHECKFLAGSNEW(GALILEO, S5B, S7)
2100 CHECKFLAGSNEW(GALILEO, C5AB, C8)
2101 CHECKFLAGSNEW(GALILEO, L5AB, L8)
2102 CHECKFLAGSNEW(GALILEO, D5AB, D8)
2103 CHECKFLAGSNEW(GALILEO, S5AB, S8)
2104
2105 if(modified)
2106 {
2107 if(hdata)
2108 hdata->data.named.typesofobsE = buffer;
2109 i = 1+snprintf(buffer, buffersize,
2110 "E %3d%-52.52s SYS / # / OBS TYPES",
2111 Parser->info[RTCM3_MSM_GALILEO].numtypes, Parser->fieldbufferGALILEO);
2112 if(Parser->info[RTCM3_MSM_GALILEO].numtypes>13)
2113 {
2114 i += snprintf(buffer+i-1, buffersize,
2115 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferGALILEO+13*4);
2116 }
2117 buffer += i; buffersize -= i;
2118 }
2119
2120 INITFLAGS(COMPASS)
2121 CHECKFLAGSNEW(COMPASS, CB1, C2I)
2122 CHECKFLAGSNEW(COMPASS, LB1, L2I)
2123 CHECKFLAGSNEW(COMPASS, DB1, D2I)
2124 CHECKFLAGSNEW(COMPASS, SB1, S2I)
2125 CHECKFLAGSNEW(COMPASS, CB2, C7I)
2126 CHECKFLAGSNEW(COMPASS, LB2, L7I)
2127 CHECKFLAGSNEW(COMPASS, DB2, D7I)
2128 CHECKFLAGSNEW(COMPASS, SB2, S7I)
2129 CHECKFLAGSNEW(COMPASS, CB3, C6I)
2130 CHECKFLAGSNEW(COMPASS, LB3, L6I)
2131 CHECKFLAGSNEW(COMPASS, DB3, D6I)
2132 CHECKFLAGSNEW(COMPASS, SB3, S6I)
2133
2134 if(modified)
2135 {
2136 if(hdata)
2137 hdata->data.named.typesofobsC = buffer;
2138 i = 1+snprintf(buffer, buffersize,
2139 "C %3d%-52.52s SYS / # / OBS TYPES",
2140 Parser->info[RTCM3_MSM_COMPASS].numtypes, Parser->fieldbufferCOMPASS);
2141 if(Parser->info[RTCM3_MSM_COMPASS].numtypes>13)
2142 {
2143 i += snprintf(buffer+i-1, buffersize,
2144 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferCOMPASS+13*4);
2145 }
2146 buffer += i; buffersize -= i;
2147 }
2148
2149 INITFLAGS(QZSS)
2150
2151 CHECKFLAGSNEW(QZSS, C1, C1C)
2152 CHECKFLAGSNEW(QZSS, L1C, L1C)
2153 CHECKFLAGSNEW(QZSS, D1C, D1C)
2154 CHECKFLAGSNEW(QZSS, S1C, S1C)
2155
2156 CHECKFLAGSNEW(QZSS, CSAIF, C1Z)
2157 CHECKFLAGSNEW(QZSS, LSAIF, L1Z)
2158 CHECKFLAGSNEW(QZSS, DSAIF, D1Z)
2159 CHECKFLAGSNEW(QZSS, SSAIF, S1Z)
2160
2161 CHECKFLAGSNEW(QZSS, C1N, C1)
2162 CHECKFLAGSNEW(QZSS, L1N, L1)
2163 CHECKFLAGSNEW(QZSS, D1N, D1)
2164 CHECKFLAGSNEW(QZSS, S1N, S1)
2165
2166 CHECKFLAGSNEW(QZSS, C6, C6)
2167 CHECKFLAGSNEW(QZSS, L6, L6)
2168 CHECKFLAGSNEW(QZSS, D6, D6)
2169 CHECKFLAGSNEW(QZSS, S6, S6)
2170
2171 CHECKFLAGSNEW(QZSS, C2, C2)
2172 CHECKFLAGSNEW(QZSS, L2C, L2)
2173 CHECKFLAGSNEW(QZSS, D2C, D2)
2174 CHECKFLAGSNEW(QZSS, S2C, S2)
2175
2176 CHECKFLAGSNEW(QZSS, C5, C5)
2177 CHECKFLAGSNEW(QZSS, L5, L5)
2178 CHECKFLAGSNEW(QZSS, D5, D5)
2179 CHECKFLAGSNEW(QZSS, S5, S5)
2180
2181 if(modified)
2182 {
2183 if(hdata)
2184 hdata->data.named.typesofobsJ = buffer;
2185 i = 1+snprintf(buffer, buffersize,
2186 "J %3d%-52.52s SYS / # / OBS TYPES",
2187 Parser->info[RTCM3_MSM_QZSS].numtypes, Parser->fieldbufferQZSS);
2188 if(Parser->info[RTCM3_MSM_QZSS].numtypes>13)
2189 {
2190 i += snprintf(buffer+i-1, buffersize,
2191 "\n %-52.52s SYS / # / OBS TYPES", Parser->fieldbufferQZSS+13*4);
2192 }
2193 buffer += i; buffersize -= i;
2194 }
2195 }
2196 else
2197 {
2198#define CHECKFLAGS(a, b) \
2199 if(flags & GNSSDF_##a##DATA) \
2200 { \
2201 if(Parser->datafields[RINEXENTRY_##b##DATA]) \
2202 { \
2203 Parser->info[RTCM3_MSM_GPS].flags[Parser->datafields[\
2204 RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
2205 Parser->info[RTCM3_MSM_GPS].pos[Parser->datafields[\
2206 RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
2207 } \
2208 else \
2209 { \
2210 Parser->flags[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSDF_##a##DATA; \
2211 Parser->pos[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSENTRY_##a##DATA; \
2212 Parser->datafields[RINEXENTRY_##b##DATA] = \
2213 ++Parser->info[RTCM3_MSM_GPS].numtypes; \
2214 snprintf(Parser->fieldbuffer+6*Parser->numdatafields, \
2215 sizeof(Parser->fieldbuffer)-6*Parser->numdatafields, " "#b); \
2216 ++Parser->numdatafields; \
2217 ++modified; \
2218 } \
2219 }
2220
2221 int flags = Parser->startflags;
2222 for(i = 0; i < Parser->Data.numsats; ++i)
2223 flags |= Parser->Data.dataflags[i];
2224
2225 CHECKFLAGS(C1,C1)
2226 CHECKFLAGS(C2,C2)
2227 CHECKFLAGS(P1,P1)
2228 CHECKFLAGS(P2,P2)
2229 CHECKFLAGS(L1C,L1)
2230 CHECKFLAGS(L1P,L1)
2231 CHECKFLAGS(L2C,L2)
2232 CHECKFLAGS(L2P,L2)
2233 CHECKFLAGS(D1C,D1)
2234 CHECKFLAGS(D1P,D1)
2235 CHECKFLAGS(D2C,D2)
2236 CHECKFLAGS(D2P,D2)
2237 CHECKFLAGS(S1C,S1)
2238 CHECKFLAGS(S1P,S1)
2239 CHECKFLAGS(S2C,S2)
2240 CHECKFLAGS(S2P,S2)
2241 CHECKFLAGS(C5,C5)
2242 CHECKFLAGS(L5,L5)
2243 CHECKFLAGS(D5,D5)
2244 CHECKFLAGS(S5,S5)
2245 CHECKFLAGS(C5AB,C8)
2246 CHECKFLAGS(L5AB,L8)
2247 CHECKFLAGS(D5AB,D8)
2248 CHECKFLAGS(S5AB,S8)
2249 CHECKFLAGS(C5B,C7)
2250 CHECKFLAGS(L5B,L7)
2251 CHECKFLAGS(D5B,D7)
2252 CHECKFLAGS(S5B,S7)
2253 CHECKFLAGS(C6,C6)
2254 CHECKFLAGS(L6,L6)
2255 CHECKFLAGS(D6,D6)
2256 CHECKFLAGS(S6,S6)
2257 /* Skip C1N and SAIF for RINEX2! */
2258
2259 if(hdata)
2260 hdata->data.named.typesofobs = buffer;
2261 if(modified)
2262 {
2263 i = 1+snprintf(buffer, buffersize,
2264 "%6d%-54.54s# / TYPES OF OBSERV", Parser->info[RTCM3_MSM_GPS].numtypes,
2265 Parser->fieldbuffer);
2266 if(Parser->info[RTCM3_MSM_GPS].numtypes>9)
2267 {
2268 i += snprintf(buffer+i-1, buffersize,
2269 "\n %-54.54s# / TYPES OF OBSERV", Parser->fieldbuffer+9*6);
2270 }
2271 if(Parser->info[RTCM3_MSM_GPS].numtypes>18)
2272 {
2273 i += snprintf(buffer+i-1, buffersize,
2274 "\n %-54.54s# / TYPES OF OBSERV", Parser->fieldbuffer+18*6);
2275 }
2276 buffer += i; buffersize -= i;
2277 }
2278 }
2279 return buffersizeold - buffersize;
2280}
2281
2282void HandleHeader(struct RTCM3ParserData *Parser)
2283{
2284#ifdef NO_RTCM3_MAIN
2285 int flags, modified = 0;
2286 if(Parser->allflags == 0)
2287 Parser->allflags = ~0;
2288 flags = Parser->allflags;
2289 if(Parser->rinex3)
2290 {
2291 struct HeaderData *hdata = 0;
2292 CHECKFLAGSNEW(GPS, C1, C1C)
2293 CHECKFLAGSNEW(GPS, L1C, L1C)
2294 CHECKFLAGSNEW(GPS, D1C, D1C)
2295 CHECKFLAGSNEW(GPS, S1C, S1C)
2296 CHECKFLAGSNEW(GPS, P1, C1P)
2297 CHECKFLAGSNEW(GPS, L1P, L1P)
2298 CHECKFLAGSNEW(GPS, D1P, D1P)
2299 CHECKFLAGSNEW(GPS, S1P, S1P)
2300 CHECKFLAGSNEW(GPS, P2, C2P)
2301 CHECKFLAGSNEW(GPS, L2P, L2P)
2302 CHECKFLAGSNEW(GPS, D2P, D2P)
2303 CHECKFLAGSNEW(GPS, S2P, S2P)
2304 CHECKFLAGSNEW(GPS, C2, C2X)
2305 CHECKFLAGSNEW(GPS, L2C, L2X)
2306 CHECKFLAGSNEW(GPS, D2C, D2X)
2307 CHECKFLAGSNEW(GPS, S2C, S2X)
2308 CHECKFLAGSNEW(GLONASS, C1, C1C)
2309 CHECKFLAGSNEW(GLONASS, L1C, L1C)
2310 CHECKFLAGSNEW(GLONASS, D1C, D1C)
2311 CHECKFLAGSNEW(GLONASS, S1C, S1C)
2312 CHECKFLAGSNEW(GLONASS, P1, C1P)
2313 CHECKFLAGSNEW(GLONASS, L1P, L1P)
2314 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2315 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2316 CHECKFLAGSNEW(GLONASS, P2, C2P)
2317 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2318 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2319 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2320 CHECKFLAGSNEW(GLONASS, C2, C2C)
2321 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2322 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2323 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2324 }
2325 else
2326 {
2327 CHECKFLAGS(C1,C1)
2328 CHECKFLAGS(C2,C2)
2329 CHECKFLAGS(P1,P1)
2330 CHECKFLAGS(P2,P2)
2331 CHECKFLAGS(L1C,L1)
2332 CHECKFLAGS(L1P,L1)
2333 CHECKFLAGS(L2C,L2)
2334 CHECKFLAGS(L2P,L2)
2335 CHECKFLAGS(D1C,D1)
2336 CHECKFLAGS(D1P,D1)
2337 CHECKFLAGS(D2C,D2)
2338 CHECKFLAGS(D2P,D2)
2339 CHECKFLAGS(S1C,S1)
2340 CHECKFLAGS(S1P,S1)
2341 CHECKFLAGS(S2C,S2)
2342 CHECKFLAGS(S2P,S2)
2343 CHECKFLAGS(C5,C5)
2344 CHECKFLAGS(L5,L5)
2345 CHECKFLAGS(D5,D5)
2346 CHECKFLAGS(S5,S5)
2347 CHECKFLAGS(C5AB,C8)
2348 CHECKFLAGS(L5AB,L8)
2349 CHECKFLAGS(D5AB,D8)
2350 CHECKFLAGS(S5AB,S8)
2351 CHECKFLAGS(C5B,C7)
2352 CHECKFLAGS(L5B,L7)
2353 CHECKFLAGS(D5B,D7)
2354 CHECKFLAGS(S5B,S7)
2355 CHECKFLAGS(C6,C6)
2356 CHECKFLAGS(L6,L6)
2357 CHECKFLAGS(D6,D6)
2358 CHECKFLAGS(S6,S6)
2359 }
2360#else /* NO_RTCM3_MAIN */
2361 struct HeaderData hdata;
2362 char thebuffer[MAXHEADERBUFFERSIZE];
2363 char *buffer = thebuffer;
2364 size_t buffersize = sizeof(thebuffer);
2365 int i;
2366
2367 memset(&hdata, 0, sizeof(hdata));
2368
2369 hdata.data.named.version = buffer;
2370 i = 1+snprintf(buffer, buffersize,
2371 "%9.2f OBSERVATION DATA M (Mixed)"
2372 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
2373 buffer += i; buffersize -= i;
2374
2375 {
2376 const char *str;
2377 hdata.data.named.pgm = buffer;
2378 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
2379 buffer += i; buffersize -= i;
2380 hdata.data.named.observer = buffer;
2381 i = 1+snprintf(buffer, buffersize,
2382 "%-20.20s "
2383 "OBSERVER / AGENCY", str);
2384 buffer += i; buffersize -= i;
2385 }
2386
2387 hdata.data.named.marker =
2388 "RTCM3TORINEX "
2389 "MARKER NAME";
2390
2391 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
2392 "GEODETIC "
2393 "MARKER TYPE";
2394
2395 hdata.data.named.receiver =
2396 " "
2397 "REC # / TYPE / VERS";
2398
2399 hdata.data.named.antenna =
2400 " "
2401 "ANT # / TYPE";
2402
2403 hdata.data.named.position =
2404 " .0000 .0000 .0000 "
2405 "APPROX POSITION XYZ";
2406
2407 hdata.data.named.antennaposition =
2408 " .0000 .0000 .0000 "
2409 "ANTENNA: DELTA H/E/N";
2410
2411 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
2412 " 1 1 "
2413 "WAVELENGTH FACT L1/2";
2414
2415 hdata.numheaders = 18;
2416
2417 i = HandleObsHeader(Parser, buffer, buffersize, &hdata);
2418 buffer += i; buffersize -= i;
2419
2420 {
2421 struct converttimeinfo cti;
2422 converttime(&cti, Parser->Data.week,
2423 (int)floor(Parser->Data.timeofweek/1000.0));
2424 hdata.data.named.timeoffirstobs = buffer;
2425 i = 1+snprintf(buffer, buffersize,
2426 " %4d %2d %2d %2d %2d %10.7f GPS "
2427 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
2428 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
2429
2430 buffer += i; buffersize -= i;
2431 }
2432
2433 if(Parser->headerfile)
2434 {
2435 FILE *fh;
2436 if((fh = fopen(Parser->headerfile, "r")))
2437 {
2438 size_t siz;
2439 char *lastblockstart;
2440 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
2441 {
2442 buffer[siz] = '\n';
2443 if(siz == buffersize)
2444 {
2445 RTCM3Error("Header file is too large. Only %d bytes read.",
2446 (int)siz);
2447 }
2448 /* scan the file line by line and enter the entries in the list */
2449 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
2450 /* overwrites entries, except for comments */
2451 lastblockstart = buffer;
2452 for(i = 0; i < (int)siz; ++i)
2453 {
2454 if(buffer[i] == '\n')
2455 { /* we found a line */
2456 char *end;
2457 while(buffer[i+1] == '\r')
2458 ++i; /* skip \r in case there are any */
2459 end = buffer+i;
2460 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
2461 *(end--) = 0;
2462 if(end-lastblockstart < 60+5) /* short line */
2463 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
2464 else
2465 {
2466 int pos;
2467 if(!strcmp("COMMENT", lastblockstart+60))
2468 pos = hdata.numheaders;
2469 else
2470 {
2471 for(pos = 0; pos < hdata.numheaders; ++pos)
2472 {
2473 if(hdata.data.unnamed[pos] &&
2474 !strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2475 break;
2476 }
2477 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2478 || !strcmp("SYS / # / OBS TYPES", lastblockstart+60)
2479 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2480 {
2481 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2482 lastblockstart+60);
2483 }
2484 }
2485 if(pos >= MAXHEADERLINES)
2486 {
2487 RTCM3Error("Maximum number of header lines of %d reached.\n",
2488 MAXHEADERLINES);
2489 }
2490 else if(!strcmp("END OF HEADER", lastblockstart+60))
2491 {
2492 RTCM3Error("End of header ignored.\n");
2493 }
2494 else
2495 {
2496 hdata.data.unnamed[pos] = lastblockstart;
2497 if(pos == hdata.numheaders)
2498 ++hdata.numheaders;
2499 }
2500 }
2501 lastblockstart = buffer+i+1;
2502 }
2503 }
2504 }
2505 else
2506 {
2507 RTCM3Error("Could not read data from headerfile '%s'.\n",
2508 Parser->headerfile);
2509 }
2510 fclose(fh);
2511 }
2512 else
2513 {
2514 RTCM3Error("Could not open header datafile '%s'.\n",
2515 Parser->headerfile);
2516 }
2517 }
2518
2519 for(i = 0; i < hdata.numheaders; ++i)
2520 {
2521 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2522 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2523 }
2524 RTCM3Text(" "
2525 "END OF HEADER\n");
2526#endif
2527}
2528
2529static void ConvLine(FILE *file, const char *fmt, ...)
2530{
2531 char buffer[100], *b;
2532 va_list v;
2533 va_start(v, fmt);
2534 vsnprintf(buffer, sizeof(buffer), fmt, v);
2535 for(b = buffer; *b; ++b)
2536 {
2537 if(*b == 'e') *b = 'D';
2538 }
2539 fprintf(file, "%s", buffer);
2540 va_end(v);
2541}
2542
2543void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2544{
2545 Parser->Message[Parser->MessageSize++] = byte;
2546 if(Parser->MessageSize >= Parser->NeedBytes)
2547 {
2548 int r;
2549 while((r = RTCM3Parser(Parser)))
2550 {
2551 if(r == 1020 || r == 1019 || r == 1044 || r == 1043)
2552 {
2553 FILE *file = 0;
2554
2555 if(Parser->rinex3 && !(file = Parser->gpsfile))
2556 {
2557 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris
2558 : Parser->qzssephemeris ? Parser->qzssephemeris : Parser->glonassephemeris;
2559 if(n)
2560 {
2561 if(!(Parser->gpsfile = fopen(n, "w")))
2562 {
2563 RTCM3Error("Could not open ephemeris output file.\n");
2564 }
2565 else
2566 {
2567 char buffer[100];
2568 fprintf(Parser->gpsfile,
2569 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2570 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2571 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2572 }
2573 Parser->qzssephemeris = 0;
2574 Parser->gpsephemeris = 0;
2575 Parser->glonassephemeris = 0;
2576 Parser->sbasephemeris = 0;
2577 file = Parser->gpsfile;
2578 }
2579 }
2580 else
2581 {
2582 if(r == 1020)
2583 {
2584 if(Parser->glonassephemeris)
2585 {
2586 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2587 {
2588 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2589 }
2590 else
2591 {
2592 char buffer[100];
2593 fprintf(Parser->glonassfile,
2594 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2595 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2596 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2597 }
2598 Parser->glonassephemeris = 0;
2599 }
2600 file = Parser->glonassfile;
2601 }
2602 else if(r == 1019)
2603 {
2604 if(Parser->gpsephemeris)
2605 {
2606 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2607 {
2608 RTCM3Error("Could not open GPS ephemeris output file.\n");
2609 }
2610 else
2611 {
2612 char buffer[100];
2613 fprintf(Parser->gpsfile,
2614 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2615 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2616 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2617 }
2618 Parser->gpsephemeris = 0;
2619 }
2620 file = Parser->gpsfile;
2621 }
2622 else if(r == 1043)
2623 {
2624 if(Parser->sbasephemeris)
2625 {
2626 if(!(Parser->sbasfile = fopen(Parser->sbasephemeris, "w")))
2627 {
2628 RTCM3Error("Could not open SBAS ephemeris output file.\n");
2629 }
2630 else
2631 {
2632 char buffer[100];
2633 fprintf(Parser->sbasfile,
2634 "%9.2f%11sN: SBAS NAV DATA%24sRINEX VERSION / TYPE\n", 2.1, "", "");
2635 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2636 fprintf(Parser->sbasfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2637 }
2638 Parser->sbasephemeris = 0;
2639 }
2640 file = Parser->sbasfile;
2641 }
2642 else if(r == 1044)
2643 {
2644 if(Parser->qzssephemeris)
2645 {
2646 if(!(Parser->qzssfile = fopen(Parser->qzssephemeris, "w")))
2647 {
2648 RTCM3Error("Could not open QZSS ephemeris output file.\n");
2649 }
2650 else
2651 {
2652 char buffer[100];
2653 fprintf(Parser->qzssfile,
2654 "%9.2f%11sN: QZSS NAV DATA%24sRINEX VERSION / TYPE\n", 2.1, "", "");
2655 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2656 fprintf(Parser->qzssfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2657 }
2658 Parser->qzssephemeris = 0;
2659 }
2660 file = Parser->qzssfile;
2661 }
2662 }
2663 if(file)
2664 {
2665 const char *sep = " ";
2666 if(r == 1020)
2667 {
2668 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2669 int w = e->GPSWeek, tow = e->GPSTOW, i;
2670 struct converttimeinfo cti;
2671
2672 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2673 converttime(&cti, w, tow);
2674
2675 i = e->tk-3*60*60; if(i < 0) i += 86400;
2676
2677 if(Parser->rinex3)
2678 {
2679 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2680 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2681 cti.second, -e->tau, e->gamma, (double) i);
2682 sep = " ";
2683 }
2684 else
2685 {
2686 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2687 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2688 (double) cti.second, -e->tau, e->gamma, (double) i);
2689 }
2690 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->x_pos,
2691 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2692 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->y_pos,
2693 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2694 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->z_pos,
2695 e->z_velocity, e->z_acceleration, (double) e->E);
2696 }
2697 else if(r == 1043)
2698 {
2699 struct sbasephemeris *e = &Parser->ephemerisSBAS;
2700 struct converttimeinfo cti;
2701 converttime(&cti, e->GPSweek_TOE, e->TOE);
2702 if(Parser->rinex3)
2703 {
2704 ConvLine(file, "S%02d %04d %2d %2d %2d %2d %2d%19.12e%19.12e%19.12e\n",
2705 e->satellite-100, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2706 cti.second, e->agf0, e->agf1, (double)e->TOW);
2707 sep = " ";
2708 }
2709 else
2710 {
2711 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2712 e->satellite-100, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2713 (double)cti.second, e->agf0, e->agf1, (double)e->TOW);
2714 }
2715 /* X, health */
2716 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->x_pos,
2717 e->x_velocity, e->x_acceleration, e->URA == 15 ? 1.0 : 0.0);
2718 /* Y, accuracy */
2719 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->y_pos,
2720 e->y_velocity, e->y_acceleration, (double)e->URA);
2721 /* Z */
2722 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->z_pos,
2723 e->z_velocity, e->z_acceleration, (double)e->IODN);
2724 }
2725 else /* if(r == 1019 || r == 1044) */
2726 {
2727 struct gpsephemeris *e = &Parser->ephemerisGPS;
2728 double d; /* temporary variable */
2729 unsigned long int i; /* temporary variable */
2730 struct converttimeinfo cti;
2731 converttime(&cti, e->GPSweek, e->TOC);
2732 int qzss = 0;
2733 int num = e->satellite;
2734
2735 if(num >= PRN_QZSS_START)
2736 {
2737 qzss = 1;
2738 num -= PRN_QZSS_START-1;
2739 }
2740 if(Parser->rinex3)
2741 {
2742 ConvLine(file,
2743 "%s%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2744 qzss ? "J" : "G", num, cti.year, cti.month, cti.day, cti.hour,
2745 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2746 e->clock_driftrate);
2747 sep = " ";
2748 }
2749 else
2750 {
2751 ConvLine(file,
2752 "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2753 num, cti.year%100, cti.month, cti.day, cti.hour,
2754 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2755 e->clock_driftrate);
2756 }
2757 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2758 (double)e->IODE, e->Crs, e->Delta_n, e->M0);
2759 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->Cuc,
2760 e->e, e->Cus, e->sqrt_A);
2761 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep,
2762 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2763 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->i0,
2764 e->Crc, e->omega, e->OMEGADOT);
2765 d = 0;
2766 i = e->flags;
2767 if(i & GPSEPHF_L2CACODE)
2768 d += 2.0;
2769 if(i & GPSEPHF_L2PCODE)
2770 d += 1.0;
2771 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, e->IDOT, d,
2772 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2773 if(e->URAindex <= 6) /* URA index */
2774 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2775 else
2776 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2777 /* 15 indicates not to use satellite. We can't handle this special
2778 case, so we create a high "non"-accuracy value. */
2779 ConvLine(file, "%s%19.12e%19.12e%19.12e%19.12e\n", sep, d,
2780 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2781
2782 ConvLine(file, "%s%19.12e%19.12e\n", sep, ((double)e->TOW),
2783 (i & GPSEPHF_6HOURSFIT) ? (Parser->rinex3 ? 1 : qzss ? 4.0 : 6.0)
2784 : (Parser->rinex3 ? 0 : qzss ? 2.0 : 4.0));
2785 /* TOW */
2786 }
2787 }
2788 }
2789 else if (r == 1 || r == 2)
2790 {
2791 int i, j, o, nh=0, hl=2;
2792 char newheader[512];
2793 struct converttimeinfo cti;
2794
2795 /* skip first epochs to detect correct data types */
2796 if(Parser->init < (Parser->changeobs ? 1 : NUMSTARTSKIP))
2797 {
2798 ++Parser->init;
2799
2800 if(Parser->init == (Parser->changeobs ? 1 : NUMSTARTSKIP))
2801 HandleHeader(Parser);
2802 else
2803 {
2804 for(i = 0; i < Parser->Data.numsats; ++i)
2805 Parser->startflags |= Parser->Data.dataflags[i];
2806 continue;
2807 }
2808 }
2809 if(r == 2 && !Parser->validwarning)
2810 {
2811 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2812 " COMMENT\n");
2813 Parser->validwarning = 1;
2814 }
2815
2816 converttime(&cti, Parser->Data.week,
2817 (int)floor(Parser->Data.timeofweek/1000.0));
2818 newheader[0] = 0;
2819 if(Parser->changeobs)
2820 {
2821 nh = HandleObsHeader(Parser, newheader, sizeof(newheader), 0);
2822 for(i = 0; i < nh; ++i)
2823 {
2824 if(newheader[i] == '\n')
2825 ++hl;
2826 }
2827 }
2828 if(Parser->rinex3)
2829 {
2830 if(nh)
2831 {
2832 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 4%3d\n",
2833 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2834 + fmod(Parser->Data.timeofweek/1000.0,1.0), hl);
2835 RTCM3Text("%s\n "
2836 " END OF HEADER\n", newheader);
2837 }
2838 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f %d%3d\n",
2839 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2840 + fmod(Parser->Data.timeofweek/1000.0,1.0), 0,
2841 Parser->Data.numsats);
2842 for(i = 0; i < Parser->Data.numsats; ++i)
2843 {
2844 int sys[RTCM3_MSM_NUMSYS] = {0,0,0,0,0,0};
2845 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2846 {
2847 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2848 sys[RTCM3_MSM_GPS] = 1;
2849 }
2850 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2851 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2852 {
2853 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2854 sys[RTCM3_MSM_GLONASS] = 1;
2855 }
2856 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2857 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2858 {
2859 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2860 sys[RTCM3_MSM_GALILEO] = 1;
2861 }
2862 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2863 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2864 {
2865 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2866 sys[RTCM3_MSM_GALILEO] = 1;
2867 }
2868 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2869 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2870 {
2871 RTCM3Text("J%02d", Parser->Data.satellites[i] - (PRN_QZSS_START-1));
2872 sys[RTCM3_MSM_QZSS] = 1;
2873 }
2874 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2875 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2876 {
2877 RTCM3Text("C%02d", Parser->Data.satellites[i] - (PRN_COMPASS_START-1));
2878 sys[RTCM3_MSM_COMPASS] = 1;
2879 }
2880 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2881 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2882 {
2883 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_SBAS_START+20);
2884 sys[RTCM3_MSM_SBAS] = 1;
2885 }
2886 else
2887 {
2888 RTCM3Text("%3d", Parser->Data.satellites[i]);
2889 }
2890
2891 if(sys[RTCM3_MSM_GLONASS])
2892 {
2893 for(j = 0; j < Parser->info[RTCM3_MSM_GLONASS].numtypes; ++j)
2894 {
2895 long long df = Parser->info[RTCM3_MSM_GLONASS].flags[j];
2896 int pos = Parser->info[RTCM3_MSM_GLONASS].pos[j];
2897 if((Parser->Data.dataflags[i] & df)
2898 && !isnan(Parser->Data.measdata[i][pos])
2899 && !isinf(Parser->Data.measdata[i][pos])
2900 && (Parser->Data.codetype[i][pos]
2901 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
2902 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
2903 == Parser->Data.codetype[i][pos][1]))
2904 {
2905 char lli = ' ';
2906 char snr = ' ';
2907 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2908 {
2909 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2910 lli = '1';
2911 snr = '0'+Parser->Data.snrL1[i];
2912 }
2913 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2914 {
2915 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2916 lli = '1';
2917 snr = '0'+Parser->Data.snrL2[i];
2918 }
2919 RTCM3Text("%14.3f%c%c",
2920 Parser->Data.measdata[i][pos],lli,snr);
2921 }
2922 else
2923 { /* no or illegal data */
2924 RTCM3Text(" ");
2925 }
2926 }
2927 }
2928 else if(sys[RTCM3_MSM_GALILEO])
2929 {
2930 for(j = 0; j < Parser->info[RTCM3_MSM_GALILEO].numtypes; ++j)
2931 {
2932 long long df = Parser->info[RTCM3_MSM_GALILEO].flags[j];
2933 int pos = Parser->info[RTCM3_MSM_GALILEO].pos[j];
2934 if((Parser->Data.dataflags[i] & df)
2935 && !isnan(Parser->Data.measdata[i][pos])
2936 && !isinf(Parser->Data.measdata[i][pos])
2937 && (Parser->Data.codetype[i][pos]
2938 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
2939 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
2940 == Parser->Data.codetype[i][pos][1]))
2941 {
2942 char lli = ' ';
2943 char snr = ' ';
2944 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2945 {
2946 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2947 lli = '1';
2948 snr = '0'+Parser->Data.snrL1[i];
2949 }
2950 if(df & GNSSDF_L6DATA)
2951 {
2952 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2953 lli = '1';
2954 snr = ' ';
2955 }
2956 if(df & GNSSDF_L5DATA)
2957 {
2958 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2959 lli = '1';
2960 snr = ' ';
2961 }
2962 if(df & GNSSDF_L5BDATA)
2963 {
2964 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2965 lli = '1';
2966 snr = ' ';
2967 }
2968 if(df & GNSSDF_L5ABDATA)
2969 {
2970 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2971 lli = '1';
2972 snr = ' ';
2973 }
2974 RTCM3Text("%14.3f%c%c",
2975 Parser->Data.measdata[i][pos],lli,snr);
2976 }
2977 else
2978 { /* no or illegal data */
2979 RTCM3Text(" ");
2980 }
2981 }
2982 }
2983 else if(sys[RTCM3_MSM_COMPASS])
2984 {
2985 for(j = 0; j < Parser->info[RTCM3_MSM_COMPASS].numtypes; ++j)
2986 {
2987 long long df = Parser->info[RTCM3_MSM_COMPASS].flags[j];
2988 int pos = Parser->info[RTCM3_MSM_COMPASS].pos[j];
2989 if((Parser->Data.dataflags[i] & df)
2990 && !isnan(Parser->Data.measdata[i][pos])
2991 && !isinf(Parser->Data.measdata[i][pos])
2992 && (Parser->Data.codetype[i][pos]
2993 && Parser->info[RTCM3_MSM_COMPASS].type[pos]
2994 && Parser->info[RTCM3_MSM_COMPASS].type[pos]
2995 == Parser->Data.codetype[i][pos][1]))
2996 {
2997 char lli = ' ';
2998 char snr = ' ';
2999 if(df & GNSSDF_LB1DATA)
3000 {
3001 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB1)
3002 lli = '1';
3003 }
3004 if(df & GNSSDF_LB2DATA)
3005 {
3006 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB2)
3007 lli = '1';
3008 }
3009 if(df & GNSSDF_LB3DATA)
3010 {
3011 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB3)
3012 lli = '1';
3013 }
3014 RTCM3Text("%14.3f%c%c",
3015 Parser->Data.measdata[i][pos],lli,snr);
3016 }
3017 else
3018 { /* no or illegal data */
3019 RTCM3Text(" ");
3020 }
3021 }
3022 }
3023 else if(sys[RTCM3_MSM_QZSS])
3024 {
3025 for(j = 0; j < Parser->info[RTCM3_MSM_QZSS].numtypes; ++j)
3026 {
3027 long long df = Parser->info[RTCM3_MSM_QZSS].flags[j];
3028 int pos = Parser->info[RTCM3_MSM_QZSS].pos[j];
3029 if((Parser->Data.dataflags[i] & df)
3030 && !isnan(Parser->Data.measdata[i][pos])
3031 && !isinf(Parser->Data.measdata[i][pos])
3032 && (Parser->Data.codetype[i][pos]
3033 && Parser->info[RTCM3_MSM_QZSS].type[pos]
3034 && Parser->info[RTCM3_MSM_QZSS].type[pos]
3035 == Parser->Data.codetype[i][pos][1]))
3036 {
3037 char lli = ' ';
3038 char snr = ' ';
3039 if(df & GNSSDF_L1CDATA)
3040 {
3041 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3042 lli = '1';
3043 snr = '0'+Parser->Data.snrL1[i];
3044 }
3045 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3046 {
3047 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3048 lli = '1';
3049 snr = '0'+Parser->Data.snrL2[i];
3050 }
3051 if(df & GNSSDF_L5DATA)
3052 {
3053 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3054 lli = '1';
3055 snr = ' ';
3056 }
3057 RTCM3Text("%14.3f%c%c",
3058 Parser->Data.measdata[i][pos],lli,snr);
3059 }
3060 else
3061 { /* no or illegal data */
3062 RTCM3Text(" ");
3063 }
3064 }
3065 }
3066 else if(sys[RTCM3_MSM_SBAS])
3067 {
3068 for(j = 0; j < Parser->info[RTCM3_MSM_SBAS].numtypes; ++j)
3069 {
3070 long long df = Parser->info[RTCM3_MSM_SBAS].flags[j];
3071 int pos = Parser->info[RTCM3_MSM_SBAS].pos[j];
3072 if((Parser->Data.dataflags[i] & df)
3073 && !isnan(Parser->Data.measdata[i][pos])
3074 && !isinf(Parser->Data.measdata[i][pos])
3075 && (Parser->Data.codetype[i][pos]
3076 && Parser->info[RTCM3_MSM_SBAS].type[pos]
3077 && Parser->info[RTCM3_MSM_SBAS].type[pos]
3078 == Parser->Data.codetype[i][pos][1]))
3079 {
3080 char lli = ' ';
3081 char snr = ' ';
3082 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3083 {
3084 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3085 lli = '1';
3086 snr = '0'+Parser->Data.snrL1[i];
3087 }
3088 if(df & GNSSDF_L5DATA)
3089 {
3090 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3091 lli = '1';
3092 snr = ' ';
3093 }
3094 RTCM3Text("%14.3f%c%c",
3095 Parser->Data.measdata[i][pos],lli,snr);
3096 }
3097 else
3098 { /* no or illegal data */
3099 RTCM3Text(" ");
3100 }
3101 }
3102 }
3103 else
3104 {
3105 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
3106 {
3107 long long df = Parser->info[RTCM3_MSM_GPS].flags[j];
3108 int pos = Parser->info[RTCM3_MSM_GPS].pos[j];
3109 if((Parser->Data.dataflags[i] & df)
3110 && !isnan(Parser->Data.measdata[i][pos])
3111 && !isinf(Parser->Data.measdata[i][pos])
3112 && (Parser->Data.codetype[i][pos]
3113 && Parser->info[RTCM3_MSM_GPS].type[pos]
3114 && Parser->info[RTCM3_MSM_GPS].type[pos]
3115 == Parser->Data.codetype[i][pos][1]))
3116 {
3117 char lli = ' ';
3118 char snr = ' ';
3119 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3120 {
3121 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3122 lli = '1';
3123 snr = '0'+Parser->Data.snrL1[i];
3124 }
3125 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3126 {
3127 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3128 lli = '1';
3129 snr = '0'+Parser->Data.snrL2[i];
3130 }
3131 if(df & GNSSDF_L5DATA)
3132 {
3133 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
3134 lli = '1';
3135 snr = ' ';
3136 }
3137 RTCM3Text("%14.3f%c%c",
3138 Parser->Data.measdata[i][pos],lli,snr);
3139 }
3140 else
3141 { /* no or illegal data */
3142 RTCM3Text(" ");
3143 }
3144 }
3145 }
3146 RTCM3Text("\n");
3147 }
3148 }
3149 else
3150 {
3151 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f %d%3d",
3152 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
3153 + fmod(Parser->Data.timeofweek/1000.0,1.0), nh ? 4 : 0,
3154 Parser->Data.numsats);
3155 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
3156 {
3157 if(Parser->Data.satellites[i] <= PRN_GPS_END)
3158 RTCM3Text("G%02d", Parser->Data.satellites[i]);
3159 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
3160 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
3161 RTCM3Text("R%02d", Parser->Data.satellites[i]
3162 - (PRN_GLONASS_START-1));
3163 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3164 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3165 RTCM3Text("S%02d", Parser->Data.satellites[i]
3166 - PRN_SBAS_START+20);
3167 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3168 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3169 RTCM3Text("E%02d", Parser->Data.satellites[i]
3170 - (PRN_GALILEO_START-1));
3171 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3172 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3173 RTCM3Text("E%02d", Parser->Data.satellites[i]
3174 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3175 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3176 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3177 RTCM3Text("J%02d", Parser->Data.satellites[i]
3178 - (PRN_QZSS_START-1));
3179 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
3180 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
3181 RTCM3Text("C%02d", Parser->Data.satellites[i]
3182 - (PRN_COMPASS_START-1));
3183 else
3184 RTCM3Text("%3d", Parser->Data.satellites[i]);
3185 }
3186 RTCM3Text("\n");
3187 o = 12;
3188 j = Parser->Data.numsats - 12;
3189 while(j > 0)
3190 {
3191 RTCM3Text(" ");
3192 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
3193 {
3194 if(Parser->Data.satellites[i] <= PRN_GPS_END)
3195 RTCM3Text("G%02d", Parser->Data.satellites[i]);
3196 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
3197 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
3198 RTCM3Text("R%02d", Parser->Data.satellites[i]
3199 - (PRN_GLONASS_START-1));
3200 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
3201 && Parser->Data.satellites[i] <= PRN_SBAS_END)
3202 RTCM3Text("S%02d", Parser->Data.satellites[i]
3203 - PRN_SBAS_START+20);
3204 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
3205 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
3206 RTCM3Text("E%02d", Parser->Data.satellites[i]
3207 - (PRN_GALILEO_START-1));
3208 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
3209 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
3210 RTCM3Text("E%02d", Parser->Data.satellites[i]
3211 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
3212 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
3213 && Parser->Data.satellites[i] <= PRN_QZSS_END)
3214 RTCM3Text("J%02d", Parser->Data.satellites[i]
3215 - (PRN_QZSS_START-1));
3216 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
3217 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
3218 RTCM3Text("C%02d", Parser->Data.satellites[i]
3219 - (PRN_COMPASS_START-1));
3220 else
3221 RTCM3Text("%3d", Parser->Data.satellites[i]);
3222 }
3223 RTCM3Text("\n");
3224 j -= 12;
3225 o += 12;
3226 }
3227 if(nh)
3228 {
3229 RTCM3Text("%s\n "
3230 " END OF HEADER\n", newheader);
3231 }
3232 for(i = 0; i < Parser->Data.numsats; ++i)
3233 {
3234 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
3235 {
3236 int v = 0;
3237 long long df = Parser->flags[j];
3238 int pos = Parser->pos[j];
3239 if((Parser->Data.dataflags[i] & df)
3240 && !isnan(Parser->Data.measdata[i][pos])
3241 && !isinf(Parser->Data.measdata[i][pos]))
3242 {
3243 v = 1;
3244 }
3245 else
3246 {
3247 df = Parser->info[RTCM3_MSM_GPS].flags[j];
3248 pos = Parser->info[RTCM3_MSM_GPS].pos[j];
3249
3250 if((Parser->Data.dataflags[i] & df)
3251 && !isnan(Parser->Data.measdata[i][pos])
3252 && !isinf(Parser->Data.measdata[i][pos]))
3253 {
3254 v = 1;
3255 }
3256 }
3257
3258 if(!v)
3259 { /* no or illegal data */
3260 RTCM3Text(" ");
3261 }
3262 else
3263 {
3264 char lli = ' ';
3265 char snr = ' ';
3266 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
3267 {
3268 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
3269 lli = '1';
3270 snr = '0'+Parser->Data.snrL1[i];
3271 }
3272 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
3273 {
3274 if(Parser->Data.dataflags2[i]
3275 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
3276 {
3277 lli = '0';
3278 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
3279 lli += 1;
3280 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
3281 lli += 4;
3282 }
3283 snr = '0'+Parser->Data.snrL2[i];
3284 }
3285 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
3286 & GNSSDF2_XCORRL2))
3287 lli = '4';
3288 RTCM3Text("%14.3f%c%c",
3289 Parser->Data.measdata[i][pos],lli,snr);
3290 }
3291 if(j%5 == 4 || j == Parser->info[RTCM3_MSM_GPS].numtypes-1)
3292 RTCM3Text("\n");
3293 }
3294 }
3295 }
3296 }
3297 }
3298 }
3299}
3300
3301#ifndef NO_RTCM3_MAIN
3302static char datestr[] = "$Date: 2015-01-19 10:22:54 +0000 (Mon, 19 Jan 2015) $";
3303
3304/* The string, which is send as agent in HTTP request */
3305#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
3306
3307#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
3308
3309static const char encodingTable [64] = {
3310 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
3311 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
3312 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
3313 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
3314};
3315
3316/* does not buffer overrun, but breaks directly after an error */
3317/* returns the number of required bytes */
3318static int encode(char *buf, int size, const char *user, const char *pwd)
3319{
3320 unsigned char inbuf[3];
3321 char *out = buf;
3322 int i, sep = 0, fill = 0, bytes = 0;
3323
3324 while(*user || *pwd)
3325 {
3326 i = 0;
3327 while(i < 3 && *user) inbuf[i++] = *(user++);
3328 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
3329 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
3330 while(i < 3) {inbuf[i++] = 0; ++fill; }
3331 if(out-buf < size-1)
3332 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
3333 if(out-buf < size-1)
3334 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
3335 | ((inbuf [1] & 0xF0) >> 4)];
3336 if(out-buf < size-1)
3337 {
3338 if(fill == 2)
3339 *(out++) = '=';
3340 else
3341 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
3342 | ((inbuf [2] & 0xC0) >> 6)];
3343 }
3344 if(out-buf < size-1)
3345 {
3346 if(fill >= 1)
3347 *(out++) = '=';
3348 else
3349 *(out++) = encodingTable[inbuf [2] & 0x3F];
3350 }
3351 bytes += 4;
3352 }
3353 if(out-buf < size)
3354 *out = 0;
3355 return bytes;
3356}
3357
3358static int stop = 0;
3359
3360struct Args
3361{
3362 const char *server;
3363 const char *port;
3364 int mode;
3365 int timeout;
3366 int rinex3;
3367 int changeobs;
3368 const char *user;
3369 const char *password;
3370 const char *proxyhost;
3371 const char *proxyport;
3372 const char *nmea;
3373 const char *data;
3374 const char *headerfile;
3375 const char *sbasephemeris;
3376 const char *gpsephemeris;
3377 const char *qzssephemeris;
3378 const char *glonassephemeris;
3379};
3380
3381/* option parsing */
3382#ifdef NO_LONG_OPTS
3383#define LONG_OPT(a)
3384#else
3385#define LONG_OPT(a) a
3386static struct option opts[] = {
3387{ "data", required_argument, 0, 'd'},
3388{ "server", required_argument, 0, 's'},
3389{ "password", required_argument, 0, 'p'},
3390{ "port", required_argument, 0, 'r'},
3391{ "timeout", required_argument, 0, 't'},
3392{ "header", required_argument, 0, 'f'},
3393{ "user", required_argument, 0, 'u'},
3394{ "gpsephemeris", required_argument, 0, 'E'},
3395{ "qzssephemeris", required_argument, 0, 'Q'},
3396{ "glonassephemeris", required_argument, 0, 'G'},
3397{ "sbasephemeris", required_argument, 0, 'B'},
3398{ "rinex3", no_argument, 0, '3'},
3399{ "changeobs", no_argument, 0, 'O'},
3400{ "proxyport", required_argument, 0, 'R'},
3401{ "proxyhost", required_argument, 0, 'S'},
3402{ "nmea", required_argument, 0, 'n'},
3403{ "mode", required_argument, 0, 'M'},
3404{ "help", no_argument, 0, 'h'},
3405{0,0,0,0}};
3406#endif
3407#define ARGOPT "-d:s:p:r:t:f:u:E:G:B:Q:M:S:R:n:h3O"
3408
3409enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
3410
3411static const char *geturl(const char *url, struct Args *args)
3412{
3413 static char buf[1000];
3414 static char *Buffer = buf;
3415 static char *Bufend = buf+sizeof(buf);
3416
3417 if(strncmp("ntrip:", url, 6))
3418 return "URL must start with 'ntrip:'.";
3419 url += 6; /* skip ntrip: */
3420
3421 if(*url != '@' && *url != '/')
3422 {
3423 /* scan for mountpoint */
3424 args->data = Buffer;
3425 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
3426 *(Buffer++) = *(url++);
3427 if(Buffer == args->data)
3428 return "Mountpoint required.";
3429 else if(Buffer >= Bufend-1)
3430 return "Parsing buffer too short.";
3431 *(Buffer++) = 0;
3432 }
3433
3434 if(*url == '/') /* username and password */
3435 {
3436 ++url;
3437 args->user = Buffer;
3438 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
3439 *(Buffer++) = *(url++);
3440 if(Buffer == args->user)
3441 return "Username cannot be empty.";
3442 else if(Buffer >= Bufend-1)
3443 return "Parsing buffer too short.";
3444 *(Buffer++) = 0;
3445
3446 if(*url == ':') ++url;
3447
3448 args->password = Buffer;
3449 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3450 *(Buffer++) = *(url++);
3451 if(Buffer == args->password)
3452 return "Password cannot be empty.";
3453 else if(Buffer >= Bufend-1)
3454 return "Parsing buffer too short.";
3455 *(Buffer++) = 0;
3456 }
3457
3458 if(*url == '@') /* server */
3459 {
3460 ++url;
3461 if(*url != '@' && *url != ':')
3462 {
3463 args->server = Buffer;
3464 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
3465 *(Buffer++) = *(url++);
3466 if(Buffer == args->server)
3467 return "Servername cannot be empty.";
3468 else if(Buffer >= Bufend-1)
3469 return "Parsing buffer too short.";
3470 *(Buffer++) = 0;
3471 }
3472
3473 if(*url == ':')
3474 {
3475 ++url;
3476 args->port = Buffer;
3477 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3478 *(Buffer++) = *(url++);
3479 if(Buffer == args->port)
3480 return "Port cannot be empty.";
3481 else if(Buffer >= Bufend-1)
3482 return "Parsing buffer too short.";
3483 *(Buffer++) = 0;
3484 }
3485
3486 if(*url == '@') /* proxy */
3487 {
3488 ++url;
3489 args->proxyhost = Buffer;
3490 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
3491 *(Buffer++) = *(url++);
3492 if(Buffer == args->proxyhost)
3493 return "Proxy servername cannot be empty.";
3494 else if(Buffer >= Bufend-1)
3495 return "Parsing buffer too short.";
3496 *(Buffer++) = 0;
3497
3498 if(*url == ':')
3499 {
3500 ++url;
3501 args->proxyport = Buffer;
3502 while(*url && *url != ';' && Buffer != Bufend)
3503 *(Buffer++) = *(url++);
3504 if(Buffer == args->proxyport)
3505 return "Proxy port cannot be empty.";
3506 else if(Buffer >= Bufend-1)
3507 return "Parsing buffer too short.";
3508 *(Buffer++) = 0;
3509 }
3510 }
3511 }
3512 if(*url == ';') /* NMEA */
3513 {
3514 args->nmea = ++url;
3515 while(*url)
3516 ++url;
3517 }
3518
3519 return *url ? "Garbage at end of server string." : 0;
3520}
3521
3522static int getargs(int argc, char **argv, struct Args *args)
3523{
3524 int res = 1;
3525 int getoptr;
3526 int help = 0;
3527 char *t;
3528
3529 args->server = "www.euref-ip.net";
3530 args->port = "2101";
3531 args->timeout = 60;
3532 args->user = "";
3533 args->password = "";
3534 args->data = 0;
3535 args->headerfile = 0;
3536 args->gpsephemeris = 0;
3537 args->qzssephemeris = 0;
3538 args->sbasephemeris = 0;
3539 args->glonassephemeris = 0;
3540 args->rinex3 = 0;
3541 args->nmea = 0;
3542 args->changeobs = 0;
3543 args->proxyhost = 0;
3544 args->proxyport = "2101";
3545 args->mode = AUTO;
3546 help = 0;
3547
3548 do
3549 {
3550
3551#ifdef NO_LONG_OPTS
3552 switch((getoptr = getopt(argc, argv, ARGOPT)))
3553#else
3554 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
3555#endif
3556 {
3557 case 's': args->server = optarg; break;
3558 case 'u': args->user = optarg; break;
3559 case 'p': args->password = optarg; break;
3560 case 'd': args->data = optarg; break;
3561 case 'f': args->headerfile = optarg; break;
3562 case 'E': args->gpsephemeris = optarg; break;
3563 case 'B': args->sbasephemeris = optarg; break;
3564 case 'G': args->glonassephemeris = optarg; break;
3565 case 'Q': args->qzssephemeris = optarg; break;
3566 case 'r': args->port = optarg; break;
3567 case '3': args->rinex3 = 1; break;
3568 case 'S': args->proxyhost = optarg; break;
3569 case 'n': args->nmea = optarg; break;
3570 case 'R': args->proxyport = optarg; break;
3571 case 'O': args->changeobs = 1; break;
3572 case 'h': help=1; break;
3573 case 'M':
3574 args->mode = 0;
3575 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
3576 args->mode = NTRIP1;
3577 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
3578 args->mode = HTTP;
3579 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
3580 args->mode = RTSP;
3581 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
3582 args->mode = AUTO;
3583 else args->mode = atoi(optarg);
3584 if((args->mode == 0) || (args->mode >= END))
3585 {
3586 fprintf(stderr, "Mode %s unknown\n", optarg);
3587 res = 0;
3588 }
3589 break;
3590 case 't':
3591 args->timeout = strtoul(optarg, &t, 10);
3592 if((t && *t) || args->timeout < 0)
3593 res = 0;
3594 break;
3595
3596 case 1:
3597 {
3598 const char *err;
3599 if((err = geturl(optarg, args)))
3600 {
3601 RTCM3Error("%s\n\n", err);
3602 res = 0;
3603 }
3604 }
3605 break;
3606 case -1: break;
3607 }
3608 } while(getoptr != -1 || !res);
3609
3610 datestr[0] = datestr[7];
3611 datestr[1] = datestr[8];
3612 datestr[2] = datestr[9];
3613 datestr[3] = datestr[10];
3614 datestr[5] = datestr[12];
3615 datestr[6] = datestr[13];
3616 datestr[8] = datestr[15];
3617 datestr[9] = datestr[16];
3618 datestr[4] = datestr[7] = '-';
3619 datestr[10] = 0;
3620
3621 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
3622 {
3623 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
3624 "Please specify only one navigation file.\n");
3625 res = 0;
3626 }
3627 else if(!res || help)
3628 {
3629 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
3630 "\nUsage: %s -s server -u user ...\n"
3631 " -d " LONG_OPT("--data ") "the requested data set\n"
3632 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
3633 " -s " LONG_OPT("--server ") "the server name or address\n"
3634 " -p " LONG_OPT("--password ") "the login password\n"
3635 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
3636 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
3637 " -u " LONG_OPT("--user ") "the user name\n"
3638 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
3639 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
3640 " -Q " LONG_OPT("--qzssephemeris ") "output file for QZSS ephemeris data\n"
3641 " -B " LONG_OPT("--sbasephemeris ") "output file for SBAS ephemeris data\n"
3642 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
3643 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
3644 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
3645 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
3646 " -O " LONG_OPT("--changeobs ") "Add observation type change header lines\n"
3647 " -M " LONG_OPT("--mode ") "mode for data request\n"
3648 " Valid modes are:\n"
3649 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
3650 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
3651 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
3652 " 4, a, auto automatic detection (default)\n"
3653 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
3654 , revisionstr, datestr, argv[0], argv[0]);
3655 exit(1);
3656 }
3657 return res;
3658}
3659
3660/* let the output complete a block if necessary */
3661static void signalhandler(int sig)
3662{
3663 if(!stop)
3664 {
3665 RTCM3Error("Stop signal number %d received. "
3666 "Trying to terminate gentle.\n", sig);
3667 stop = 1;
3668 alarm(1);
3669 }
3670}
3671
3672#ifndef WINDOWSVERSION
3673static void WaitMicro(int mic)
3674{
3675 struct timeval tv;
3676 tv.tv_sec = mic/1000000;
3677 tv.tv_usec = mic%1000000;
3678#ifdef DEBUG
3679 fprintf(stderr, "Waiting %d micro seconds\n", mic);
3680#endif
3681 select(0, 0, 0, 0, &tv);
3682}
3683#else /* WINDOWSVERSION */
3684void WaitMicro(int mic)
3685{
3686 Sleep(mic/1000);
3687}
3688#endif /* WINDOWSVERSION */
3689
3690#define ALARMTIME (2*60)
3691
3692/* for some reason we had to abort hard (maybe waiting for data */
3693#ifdef __GNUC__
3694static __attribute__ ((noreturn)) void signalhandler_alarm(
3695int sig __attribute__((__unused__)))
3696#else /* __GNUC__ */
3697static void signalhandler_alarm(int sig)
3698#endif /* __GNUC__ */
3699{
3700 RTCM3Error("Programm forcefully terminated.\n");
3701 exit(1);
3702}
3703
3704int main(int argc, char **argv)
3705{
3706 struct Args args;
3707 struct RTCM3ParserData Parser;
3708
3709 setbuf(stdout, 0);
3710 setbuf(stdin, 0);
3711 setbuf(stderr, 0);
3712
3713 fixrevision();
3714
3715 signal(SIGINT, signalhandler);
3716 signal(SIGALRM,signalhandler_alarm);
3717 signal(SIGQUIT,signalhandler);
3718 signal(SIGTERM,signalhandler);
3719 signal(SIGPIPE,signalhandler);
3720 memset(&Parser, 0, sizeof(Parser));
3721 {
3722 time_t tim;
3723 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
3724 Parser.GPSWeek = tim/(7*24*60*60);
3725 Parser.GPSTOW = tim%(7*24*60*60);
3726 }
3727
3728 if(getargs(argc, argv, &args))
3729 {
3730 int sockfd, numbytes;
3731 char buf[MAXDATASIZE];
3732 struct sockaddr_in their_addr; /* connector's address information */
3733 struct hostent *he;
3734 struct servent *se;
3735 const char *server, *port, *proxyserver = 0;
3736 char proxyport[6];
3737 char *b;
3738 long i;
3739 struct timeval tv;
3740
3741 alarm(ALARMTIME);
3742
3743 Parser.headerfile = args.headerfile;
3744 Parser.glonassephemeris = args.glonassephemeris;
3745 Parser.gpsephemeris = args.gpsephemeris;
3746 Parser.qzssephemeris = args.qzssephemeris;
3747 Parser.sbasephemeris = args.sbasephemeris;
3748 Parser.rinex3 = args.rinex3;
3749 Parser.changeobs = args.changeobs;
3750
3751 if(args.proxyhost)
3752 {
3753 int p;
3754 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
3755 p = i;
3756 else if(!(se = getservbyname(args.port, 0)))
3757 {
3758 RTCM3Error("Can't resolve port %s.", args.port);
3759 exit(1);
3760 }
3761 else
3762 {
3763 p = ntohs(se->s_port);
3764 }
3765 snprintf(proxyport, sizeof(proxyport), "%d", p);
3766 port = args.proxyport;
3767 proxyserver = args.server;
3768 server = args.proxyhost;
3769 }
3770 else
3771 {
3772 server = args.server;
3773 port = args.port;
3774 }
3775
3776 memset(&their_addr, 0, sizeof(struct sockaddr_in));
3777 if((i = strtol(port, &b, 10)) && (!b || !*b))
3778 their_addr.sin_port = htons(i);
3779 else if(!(se = getservbyname(port, 0)))
3780 {
3781 RTCM3Error("Can't resolve port %s.", port);
3782 exit(1);
3783 }
3784 else
3785 {
3786 their_addr.sin_port = se->s_port;
3787 }
3788 if(!(he=gethostbyname(server)))
3789 {
3790 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3791 exit(1);
3792 }
3793 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3794 {
3795 perror("socket");
3796 exit(1);
3797 }
3798
3799 tv.tv_sec = args.timeout;
3800 tv.tv_usec = 0;
3801 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3802 {
3803 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3804 exit(1);
3805 }
3806
3807 their_addr.sin_family = AF_INET;
3808 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3809
3810 if(args.data && args.mode == RTSP)
3811 {
3812 struct sockaddr_in local;
3813 int sockudp, localport;
3814 int cseq = 1;
3815 socklen_t len;
3816
3817 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3818 {
3819 perror("socket");
3820 exit(1);
3821 }
3822 /* fill structure with local address information for UDP */
3823 memset(&local, 0, sizeof(local));
3824 local.sin_family = AF_INET;
3825 local.sin_port = htons(0);
3826 local.sin_addr.s_addr = htonl(INADDR_ANY);
3827 len = sizeof(local);
3828 /* bind() in order to get a random RTP client_port */
3829 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3830 {
3831 perror("bind");
3832 exit(1);
3833 }
3834 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3835 {
3836 localport = ntohs(local.sin_port);
3837 }
3838 else
3839 {
3840 perror("local access failed");
3841 exit(1);
3842 }
3843 if(connect(sockfd, (struct sockaddr *)&their_addr,
3844 sizeof(struct sockaddr)) == -1)
3845 {
3846 perror("connect");
3847 exit(1);
3848 }
3849 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3850 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3851 "CSeq: %d\r\n"
3852 "Ntrip-Version: Ntrip/2.0\r\n"
3853 "Ntrip-Component: Ntripclient\r\n"
3854 "User-Agent: %s/%s\r\n"
3855 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3856 "Authorization: Basic ",
3857 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3858 args.data, cseq++, AGENTSTRING, revisionstr, localport);
3859 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3860 {
3861 RTCM3Error("Requested data too long\n");
3862 exit(1);
3863 }
3864 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3865 if(i > MAXDATASIZE-4)
3866 {
3867 RTCM3Error("Username and/or password too long\n");
3868 exit(1);
3869 }
3870 buf[i++] = '\r';
3871 buf[i++] = '\n';
3872 buf[i++] = '\r';
3873 buf[i++] = '\n';
3874 if(args.nmea)
3875 {
3876 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3877 if(j >= 0 && j < MAXDATASIZE-i)
3878 i += j;
3879 else
3880 {
3881 RTCM3Error("NMEA string too long\n");
3882 exit(1);
3883 }
3884 }
3885 if(send(sockfd, buf, (size_t)i, 0) != i)
3886 {
3887 perror("send");
3888 exit(1);
3889 }
3890 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3891 {
3892 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3893 {
3894 int serverport = 0, session = 0;
3895 const char *portcheck = "server_port=";
3896 const char *sessioncheck = "session: ";
3897 int l = strlen(portcheck)-1;
3898 int j=0;
3899 for(i = 0; j != l && i < numbytes-l; ++i)
3900 {
3901 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3902 ;
3903 }
3904 if(i == numbytes-l)
3905 {
3906 RTCM3Error("No server port number found\n");
3907 exit(1);
3908 }
3909 else
3910 {
3911 i+=l;
3912 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3913 serverport = serverport * 10 + buf[i++]-'0';
3914 if(buf[i] != '\r' && buf[i] != ';')
3915 {
3916 RTCM3Error("Could not extract server port\n");
3917 exit(1);
3918 }
3919 }
3920 l = strlen(sessioncheck)-1;
3921 j=0;
3922 for(i = 0; j != l && i < numbytes-l; ++i)
3923 {
3924 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3925 ;
3926 }
3927 if(i == numbytes-l)
3928 {
3929 RTCM3Error("No session number found\n");
3930 exit(1);
3931 }
3932 else
3933 {
3934 i+=l;
3935 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3936 session = session * 10 + buf[i++]-'0';
3937 if(buf[i] != '\r')
3938 {
3939 RTCM3Error("Could not extract session number\n");
3940 exit(1);
3941 }
3942 }
3943
3944 i = snprintf(buf, MAXDATASIZE,
3945 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3946 "CSeq: %d\r\n"
3947 "Session: %d\r\n"
3948 "\r\n",
3949 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3950 args.data, cseq++, session);
3951
3952 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3953 {
3954 RTCM3Error("Requested data too long\n");
3955 exit(1);
3956 }
3957 if(send(sockfd, buf, (size_t)i, 0) != i)
3958 {
3959 perror("send");
3960 exit(1);
3961 }
3962 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3963 {
3964 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3965 {
3966 struct sockaddr_in addrRTP;
3967 /* fill structure with caster address information for UDP */
3968 memset(&addrRTP, 0, sizeof(addrRTP));
3969 addrRTP.sin_family = AF_INET;
3970 addrRTP.sin_port = htons(serverport);
3971 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3972 len = sizeof(addrRTP);
3973 int ts = 0;
3974 int sn = 0;
3975 int ssrc = 0;
3976 int init = 0;
3977 int u, v, w;
3978 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3979 (struct sockaddr*) &addrRTP, &len)) > 0)
3980 {
3981 alarm(ALARMTIME);
3982 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3983 {
3984 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3985 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3986 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3987 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3988 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3989
3990 if(init)
3991 {
3992 int z;
3993 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3994 if(ssrc != w || ts > v)
3995 {
3996 RTCM3Error("Illegal UDP data received.\n");
3997 exit(1);
3998 }
3999 if(u > sn) /* don't show out-of-order packets */
4000 for(z = 12; z < i && !stop; ++z)
4001 HandleByte(&Parser, (unsigned int) buf[z]);
4002 }
4003 sn = u; ts = v; ssrc = w; init = 1;
4004 }
4005 else
4006 {
4007 RTCM3Error("Illegal UDP header.\n");
4008 exit(1);
4009 }
4010 }
4011 }
4012 i = snprintf(buf, MAXDATASIZE,
4013 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
4014 "CSeq: %d\r\n"
4015 "Session: %d\r\n"
4016 "\r\n",
4017 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
4018 args.data, cseq++, session);
4019
4020 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
4021 {
4022 RTCM3Error("Requested data too long\n");
4023 exit(1);
4024 }
4025 if(send(sockfd, buf, (size_t)i, 0) != i)
4026 {
4027 perror("send");
4028 exit(1);
4029 }
4030 }
4031 else
4032 {
4033 RTCM3Error("Could not start data stream.\n");
4034 exit(1);
4035 }
4036 }
4037 else
4038 {
4039 RTCM3Error("Could not setup initial control connection.\n");
4040 exit(1);
4041 }
4042 }
4043 else
4044 {
4045 perror("recv");
4046 exit(1);
4047 }
4048 }
4049 else
4050 {
4051 if(connect(sockfd, (struct sockaddr *)&their_addr,
4052 sizeof(struct sockaddr)) == -1)
4053 {
4054 perror("connect");
4055 exit(1);
4056 }
4057 if(!args.data)
4058 {
4059 i = snprintf(buf, MAXDATASIZE,
4060 "GET %s%s%s%s/ HTTP/1.0\r\n"
4061 "Host: %s\r\n%s"
4062 "User-Agent: %s/%s\r\n"
4063 "Connection: close\r\n"
4064 "\r\n"
4065 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
4066 proxyserver ? ":" : "", proxyserver ? proxyport : "",
4067 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
4068 AGENTSTRING, revisionstr);
4069 }
4070 else
4071 {
4072 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
4073 "GET %s%s%s%s/%s HTTP/1.0\r\n"
4074 "Host: %s\r\n%s"
4075 "User-Agent: %s/%s\r\n"
4076 "Connection: close\r\n"
4077 "Authorization: Basic "
4078 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
4079 proxyserver ? ":" : "", proxyserver ? proxyport : "",
4080 args.data, args.server,
4081 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
4082 AGENTSTRING, revisionstr);
4083 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
4084 {
4085 RTCM3Error("Requested data too long\n");
4086 exit(1);
4087 }
4088 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
4089 if(i > MAXDATASIZE-4)
4090 {
4091 RTCM3Error("Username and/or password too long\n");
4092 exit(1);
4093 }
4094 buf[i++] = '\r';
4095 buf[i++] = '\n';
4096 buf[i++] = '\r';
4097 buf[i++] = '\n';
4098 if(args.nmea)
4099 {
4100 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
4101 if(j >= 0 && j < MAXDATASIZE-i)
4102 i += j;
4103 else
4104 {
4105 RTCM3Error("NMEA string too long\n");
4106 exit(1);
4107 }
4108 }
4109 }
4110 if(send(sockfd, buf, (size_t)i, 0) != i)
4111 {
4112 perror("send");
4113 exit(1);
4114 }
4115 if(args.data)
4116 {
4117 int k = 0;
4118 int chunkymode = 0;
4119 int totalbytes = 0;
4120 int chunksize = 0;
4121
4122 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
4123 {
4124 if(numbytes > 0)
4125 alarm(ALARMTIME);
4126 else
4127 {
4128 WaitMicro(100);
4129 continue;
4130 }
4131 if(!k)
4132 {
4133 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
4134 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
4135 {
4136 const char *datacheck = "Content-Type: gnss/data\r\n";
4137 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
4138 int l = strlen(datacheck)-1;
4139 int j=0;
4140 for(i = 0; j != l && i < numbytes-l; ++i)
4141 {
4142 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
4143 ;
4144 }
4145 if(i == numbytes-l)
4146 {
4147 RTCM3Error("No 'Content-Type: gnss/data' found\n");
4148 exit(1);
4149 }
4150 l = strlen(chunkycheck)-1;
4151 j=0;
4152 for(i = 0; j != l && i < numbytes-l; ++i)
4153 {
4154 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
4155 ;
4156 }
4157 if(i < numbytes-l)
4158 chunkymode = 1;
4159 }
4160 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
4161 {
4162 RTCM3Error("Could not get the requested data: ");
4163 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
4164 {
4165 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
4166 }
4167 RTCM3Error("\n");
4168 exit(1);
4169 }
4170 else if(args.mode != NTRIP1)
4171 {
4172 if(args.mode != AUTO)
4173 {
4174 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
4175 args.mode == AUTO ? ", falling back to NTRIP1" : "");
4176 }
4177 if(args.mode == HTTP)
4178 exit(1);
4179 }
4180 ++k;
4181 }
4182 else
4183 {
4184 if(chunkymode)
4185 {
4186 int stop = 0;
4187 int pos = 0;
4188 while(!stop && pos < numbytes)
4189 {
4190 switch(chunkymode)
4191 {
4192 case 1: /* reading number starts */
4193 chunksize = 0;
4194 ++chunkymode; /* no break */
4195 case 2: /* during reading number */
4196 i = buf[pos++];
4197 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
4198 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
4199 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
4200 else if(i == '\r') ++chunkymode;
4201 else if(i == ';') chunkymode = 5;
4202 else stop = 1;
4203 break;
4204 case 3: /* scanning for return */
4205 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
4206 else stop = 1;
4207 break;
4208 case 4: /* output data */
4209 i = numbytes-pos;
4210 if(i > chunksize) i = chunksize;
4211 {
4212 int z;
4213 for(z = 0; z < i && !stop; ++z)
4214 HandleByte(&Parser, (unsigned int) buf[pos+z]);
4215 }
4216 totalbytes += i;
4217 chunksize -= i;
4218 pos += i;
4219 if(!chunksize)
4220 chunkymode = 1;
4221 break;
4222 case 5:
4223 if(i == '\r') chunkymode = 3;
4224 break;
4225 }
4226 }
4227 if(stop)
4228 {
4229 RTCM3Error("Error in chunky transfer encoding\n");
4230 break;
4231 }
4232 }
4233 else
4234 {
4235 totalbytes += numbytes;
4236 {
4237 int z;
4238 for(z = 0; z < numbytes && !stop; ++z)
4239 HandleByte(&Parser, (unsigned int) buf[z]);
4240 }
4241 }
4242 if(totalbytes < 0) /* overflow */
4243 {
4244 totalbytes = 0;
4245 }
4246 }
4247 }
4248 }
4249 else
4250 {
4251 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
4252 {
4253 alarm(ALARMTIME);
4254 fwrite(buf, (size_t)numbytes, 1, stdout);
4255 }
4256 }
4257 close(sockfd);
4258 }
4259 }
4260 return 0;
4261}
4262#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.