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

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

first test of Galileo ephemeris type 1045

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