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

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

fix segfault

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