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

Last change on this file since 5660 was 5660, checked in by stoecker, 10 years ago

change lockloss handling

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