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

Last change on this file since 4417 was 4417, checked in by stoecker, 12 years ago

added support functions

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