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

Last change on this file since 6771 was 6771, checked in by stoecker, 7 years ago

correct 1046/1045

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