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

Last change on this file since 2873 was 2873, checked in by stoecker, 13 years ago

reverse doppler

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