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

Last change on this file since 5358 was 5358, checked in by stoecker, 11 years ago

add changeobs option and some other smaller improvements

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