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

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

support type 1043 sbas ephemeris

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