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

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

add QZSS (type 1044)

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