source: ntrip/trunk/clock_and_orbit/lib/rtcm3torinex.c@ 6210

Last change on this file since 6210 was 6210, checked in by stuerze, 10 years ago

added to have them available in readRTCM3()

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