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

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

fix codetype

  • Property svn:keywords set to Id Revision Date
File size: 128.0 KB
Line 
1/*
2 Converter for RTCM3 data to RINEX.
3 $Id: rtcm3torinex.c 4374 2012-07-04 09:45:16Z stoecker $
4 Copyright (C) 2005-2008 by Dirk Stöcker <stoecker@alberding.eu>
5
6 This software is a complete NTRIP-RTCM3 to RINEX converter as well as
7 a module of the BNC tool for multiformat conversion. Contact Dirk
8 Stöcker for suggestions and bug reports related to the RTCM3 to RINEX
9 conversion problems and the author of BNC for all the other problems.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 or read http://www.gnu.org/licenses/gpl.txt
25*/
26
27#include <ctype.h>
28#include <errno.h>
29#include <math.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/types.h>
36#include <time.h>
37#include <unistd.h>
38
39#ifndef NO_RTCM3_MAIN
40#include <getopt.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#endif
45
46#ifndef sparc
47#include <stdint.h>
48#endif
49
50#ifndef isinf
51#define isinf(x) 0
52#endif
53
54#include "rtcm3torinex.h"
55
56/* CVS revision and version */
57static char revisionstr[] = "$Revision: 4374 $";
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 switch(sys)
1199 {
1200 case RTCM3_MSM_COMPASS:
1201 case RTCM3_MSM_GALILEO: /* use DF004 instead of DF248 */
1202 case RTCM3_MSM_QZSS:
1203 case RTCM3_MSM_SBAS:
1204 case RTCM3_MSM_GPS:
1205 GETBITS(i,30)
1206 if(i/1000 < (int)handle->GPSTOW - 86400)
1207 ++handle->GPSWeek;
1208 handle->GPSTOW = i/1000;
1209 break;
1210 case RTCM3_MSM_GLONASS:
1211 SKIPBITS(3)
1212 GETBITS(i,27) /* tk */
1213
1214 updatetime(&handle->GPSWeek, &handle->GPSTOW, i, 0); /* Moscow -> GPS */
1215 i = handle->GPSTOW*1000;
1216 break;
1217 }
1218
1219 if(gnss->week && (gnss->timeofweek != i || gnss->week
1220 != handle->GPSWeek))
1221 {
1222 handle->Data = *gnss;
1223 memset(gnss, 0, sizeof(*gnss));
1224 old = 1;
1225 }
1226 gnss->timeofweek = i;
1227 gnss->week = handle->GPSWeek;
1228
1229 GETBITS(syncf, 1)
1230 SKIPBITS(3+7+2+2+1+3)
1231 GETBITS64(satmask, RTCM3_MSM_NUMSAT)
1232
1233 /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
1234 for(ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
1235 ++numsat;
1236 GETBITS(sigmask, RTCM3_MSM_NUMSIG)
1237 for(i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
1238 ++numsig;
1239 i = numsat*numsig;
1240 GETBITS64(cellmask, (unsigned)i)
1241
1242 switch(type % 10)
1243 {
1244 case 1: case 2: case 3:
1245 ++wasnoamb;
1246 for(j = numsat; j--;)
1247 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1248 break;
1249 case 4: case 6:
1250 for(j = numsat; j--;)
1251 GETBITS(rrint[j], 8)
1252 for(j = numsat; j--;)
1253 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1254 break;
1255 case 5: case 7:
1256 for(j = numsat; j--;)
1257 GETBITS(rrint[j], 8)
1258 for(j = numsat; j--;)
1259 GETBITS(extsat[j], 4)
1260 for(j = numsat; j--;)
1261 GETFLOAT(rrmod[j], 10, 1.0/1024.0)
1262 for(j = numsat; j--;)
1263 GETBITSSIGN(rdop[j], 14)
1264 break;
1265 }
1266
1267 numcells = numsat*numsig;
1268 if(numcells <= RTCM3_MSM_NUMCELLS)
1269 {
1270 switch(type % 10)
1271 {
1272 case 1:
1273 for(count = numcells; count--;)
1274 if(cellmask & (UINT64(1)<<count))
1275 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1276 break;
1277 case 2:
1278 for(count = numcells; count--;)
1279 if(cellmask & (UINT64(1)<<count))
1280 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1281 for(count = numcells; count--;)
1282 if(cellmask & (UINT64(1)<<count))
1283 GETBITS(ll[count], 4)
1284 for(count = numcells; count--;)
1285 if(cellmask & (UINT64(1)<<count))
1286 GETBITS(hc[count], 1)
1287 break;
1288 case 3:
1289 for(count = numcells; count--;)
1290 if(cellmask & (UINT64(1)<<count))
1291 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1292 for(count = numcells; count--;)
1293 if(cellmask & (UINT64(1)<<count))
1294 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1295 for(count = numcells; count--;)
1296 if(cellmask & (UINT64(1)<<count))
1297 GETBITS(ll[count], 4)
1298 for(count = numcells; count--;)
1299 if(cellmask & (UINT64(1)<<count))
1300 GETBITS(hc[count], 1)
1301 break;
1302 case 4:
1303 for(count = numcells; count--;)
1304 if(cellmask & (UINT64(1)<<count))
1305 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1306 for(count = numcells; count--;)
1307 if(cellmask & (UINT64(1)<<count))
1308 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1309 for(count = numcells; count--;)
1310 if(cellmask & (UINT64(1)<<count))
1311 GETBITS(ll[count], 4)
1312 for(count = numcells; count--;)
1313 if(cellmask & (UINT64(1)<<count))
1314 GETBITS(hc[count], 1)
1315 for(count = numcells; count--;)
1316 if(cellmask & (UINT64(1)<<count))
1317 GETBITS(cnr[count], 6)
1318 break;
1319 case 5:
1320 for(count = numcells; count--;)
1321 if(cellmask & (UINT64(1)<<count))
1322 GETFLOATSIGN(psr[count], 15, 1.0/(1<<24))
1323 for(count = numcells; count--;)
1324 if(cellmask & (UINT64(1)<<count))
1325 GETFLOATSIGN(cp[count], 22, 1.0/(1<<29))
1326 for(count = numcells; count--;)
1327 if(cellmask & (UINT64(1)<<count))
1328 GETBITS(ll[count], 4)
1329 for(count = numcells; count--;)
1330 if(cellmask & (UINT64(1)<<count))
1331 GETBITS(hc[count], 1)
1332 for(count = numcells; count--;)
1333 if(cellmask & (UINT64(1)<<count))
1334 GETFLOAT(cnr[count], 6, 1.0)
1335 for(count = numcells; count--;)
1336 if(cellmask & (UINT64(1)<<count))
1337 GETFLOATSIGN(dop[count], 15, 0.0001)
1338 break;
1339 case 6:
1340 for(count = numcells; count--;)
1341 if(cellmask & (UINT64(1)<<count))
1342 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1343 for(count = numcells; count--;)
1344 if(cellmask & (UINT64(1)<<count))
1345 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1346 for(count = numcells; count--;)
1347 if(cellmask & (UINT64(1)<<count))
1348 GETBITS(ll[count], 10)
1349 for(count = numcells; count--;)
1350 if(cellmask & (UINT64(1)<<count))
1351 GETBITS(hc[count], 1)
1352 for(count = numcells; count--;)
1353 if(cellmask & (UINT64(1)<<count))
1354 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1355 break;
1356 case 7:
1357 for(count = numcells; count--;)
1358 if(cellmask & (UINT64(1)<<count))
1359 GETFLOATSIGN(psr[count], 20, 1.0/(1<<29))
1360 for(count = numcells; count--;)
1361 if(cellmask & (UINT64(1)<<count))
1362 GETFLOATSIGN(cp[count], 24, 1.0/(1U<<31))
1363 for(count = numcells; count--;)
1364 if(cellmask & (UINT64(1)<<count))
1365 GETBITS(ll[count], 10)
1366 for(count = numcells; count--;)
1367 if(cellmask & (UINT64(1)<<count))
1368 GETBITS(hc[count], 1)
1369 for(count = numcells; count--;)
1370 if(cellmask & (UINT64(1)<<count))
1371 GETFLOAT(cnr[count], 10, 1.0/(1<<4))
1372 for(count = numcells; count--;)
1373 if(cellmask & (UINT64(1)<<count))
1374 GETFLOATSIGN(dop[count], 15, 0.0001)
1375 break;
1376 }
1377 i = RTCM3_MSM_NUMSAT;
1378 j = -1;
1379 for(count = numcells; count--;)
1380 {
1381 while(j >= 0 && !(sigmask&(1<<--j)))
1382 ;
1383 if(j < 0)
1384 {
1385 while(!(satmask&(UINT64(1)<<(--i)))) /* next satellite */
1386 ;
1387 j = RTCM3_MSM_NUMSIG;
1388 while(!(sigmask&(1<<--j)))
1389 ;
1390 --numsat;
1391 }
1392 if(cellmask & (UINT64(1)<<count))
1393 {
1394 struct CodeData cd = {0,0,0,0,0,0,0};
1395 double wl = 0.0;
1396 switch(sys)
1397 {
1398 case RTCM3_MSM_QZSS:
1399 cd = qzss[RTCM3_MSM_NUMSIG-j-1];
1400 wl = cd.wl;
1401 break;
1402 case RTCM3_MSM_COMPASS:
1403 cd = compass[RTCM3_MSM_NUMSIG-j-1];
1404 wl = cd.wl;
1405 break;
1406 case RTCM3_MSM_GPS: case RTCM3_MSM_SBAS:
1407 cd = gps[RTCM3_MSM_NUMSIG-j-1];
1408 wl = cd.wl;
1409 break;
1410 case RTCM3_MSM_GLONASS: cd = glo[RTCM3_MSM_NUMSIG-j-1];
1411 {
1412 int k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1];
1413 if(!k && extsat[count] < 14)
1414 {
1415 k = handle->GLOFreq[RTCM3_MSM_NUMSAT-i-1]
1416 = 100+extsat[count]-7;
1417 }
1418 if(k)
1419 {
1420 if(cd.wl == 0.0)
1421 wl = GLO_WAVELENGTH_L1(k-100);
1422 else if(cd.wl == 1.0)
1423 wl = GLO_WAVELENGTH_L2(k-100);
1424 }
1425 }
1426 break;
1427 case RTCM3_MSM_GALILEO: cd = gal[RTCM3_MSM_NUMSIG-j-1];
1428 wl = cd.wl;
1429 break;
1430 }
1431 if(cd.lock && wl) /* lock cannot have a valid zero value */
1432 {
1433 int fullsat = RTCM3_MSM_NUMSAT-i-1, num;
1434
1435 if(sys == RTCM3_MSM_GALILEO && fullsat >= 50 && fullsat <= 51)
1436 fullsat += PRN_GIOVE_START-50;
1437 else
1438 fullsat += start;
1439
1440 for(num = 0; num < gnss->numsats
1441 && fullsat != gnss->satellites[num]; ++num)
1442 ;
1443
1444 if(num == gnss->numsats)
1445 gnss->satellites[gnss->numsats++] = fullsat;
1446
1447 gnss->codetype[num][cd.typeR] =
1448 gnss->codetype[num][cd.typeP] =
1449 gnss->codetype[num][cd.typeD] =
1450 gnss->codetype[num][cd.typeS] = cd.code;
1451 if(!handle->info[sys].type[cd.typeR])
1452 {
1453 handle->info[sys].type[cd.typeR] =
1454 handle->info[sys].type[cd.typeP] =
1455 handle->info[sys].type[cd.typeD] =
1456 handle->info[sys].type[cd.typeS] = cd.code[1];
1457 }
1458
1459 switch(type % 10)
1460 {
1461 case 1:
1462 if(psr[count] > -1.0/(1<<10))
1463 {
1464 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1465 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1466 gnss->dataflags[num] |= (1<<cd.typeR);
1467 }
1468 break;
1469 case 2:
1470 if(wl && cp[count] > -1.0/(1<<8))
1471 {
1472 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1473 +(rrmod[numsat])*LIGHTSPEED/1000.0/wl;
1474 if(handle->lastlockmsm[j][i] != ll[count])
1475 {
1476 gnss->dataflags2[num] |= cd.lock;
1477 handle->lastlockmsm[j][i] = ll[count];
1478 }
1479 gnss->dataflags[num] |= (1<<cd.typeP);
1480 }
1481 break;
1482 case 3:
1483 if(psr[count] > -1.0/(1<<10))
1484 {
1485 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1486 +(rrmod[numsat])*LIGHTSPEED/1000.0;
1487 gnss->dataflags[num] |= (1<<cd.typeR);
1488 }
1489
1490 if(wl && cp[count] > -1.0/(1<<8))
1491 {
1492 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1493 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1494 if(handle->lastlockmsm[j][i] != ll[count])
1495 {
1496 gnss->dataflags2[num] |= cd.lock;
1497 handle->lastlockmsm[j][i] = ll[count];
1498 }
1499 gnss->dataflags[num] |= (1<<cd.typeP);
1500 }
1501 break;
1502 case 4:
1503 if(psr[count] > -1.0/(1<<10))
1504 {
1505 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1506 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1507 gnss->dataflags[num] |= (1<<cd.typeR);
1508 }
1509
1510 if(wl && cp[count] > -1.0/(1<<8))
1511 {
1512 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1513 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1514 if(handle->lastlockmsm[j][i] != ll[count])
1515 {
1516 gnss->dataflags2[num] |= cd.lock;
1517 handle->lastlockmsm[j][i] = ll[count];
1518 }
1519 gnss->dataflags[num] |= (1<<cd.typeP);
1520 }
1521
1522 gnss->measdata[num][cd.typeS] = cnr[count];
1523 gnss->dataflags[num] |= (1<<cd.typeS);
1524 break;
1525 case 5:
1526 if(psr[count] > -1.0/(1<<10))
1527 {
1528 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1529 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1530 gnss->dataflags[num] |= (1<<cd.typeR);
1531 }
1532
1533 if(wl && cp[count] > -1.0/(1<<8))
1534 {
1535 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1536 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1537 if(handle->lastlockmsm[j][i] != ll[count])
1538 {
1539 gnss->dataflags2[num] |= cd.lock;
1540 handle->lastlockmsm[j][i] = ll[count];
1541 }
1542 gnss->dataflags[num] |= (1<<cd.typeP);
1543 }
1544
1545 gnss->measdata[num][cd.typeS] = cnr[count];
1546 gnss->dataflags[num] |= (1<<cd.typeS);
1547
1548 if(dop[count] > -1.6384)
1549 {
1550 gnss->measdata[num][cd.typeD] = -(dop[count]
1551 +rdop[numsat])/wl;
1552 gnss->dataflags[num] |= (1<<cd.typeD);
1553 }
1554 break;
1555 case 6:
1556 if(psr[count] > -1.0/(1<<10))
1557 {
1558 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1559 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1560 gnss->dataflags[num] |= (1<<cd.typeR);
1561 }
1562
1563 if(wl && cp[count] > -1.0/(1<<8))
1564 {
1565 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1566 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1567 if(handle->lastlockmsm[j][i] != ll[count])
1568 {
1569 gnss->dataflags2[num] |= cd.lock;
1570 handle->lastlockmsm[j][i] = ll[count];
1571 }
1572 gnss->dataflags[num] |= (1<<cd.typeP);
1573 }
1574
1575 gnss->measdata[num][cd.typeS] = cnr[count];
1576 gnss->dataflags[num] |= (1<<cd.typeS);
1577 break;
1578 case 7:
1579 if(psr[count] > -1.0/(1<<10))
1580 {
1581 gnss->measdata[num][cd.typeR] = psr[count]*LIGHTSPEED/1000.0
1582 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0;
1583 gnss->dataflags[num] |= (1<<cd.typeR);
1584 }
1585
1586 if(wl && cp[count] > -1.0/(1<<8))
1587 {
1588 gnss->measdata[num][cd.typeP] = cp[count]*LIGHTSPEED/1000.0/wl
1589 +(rrmod[numsat]+rrint[numsat])*LIGHTSPEED/1000.0/wl;
1590 if(handle->lastlockmsm[j][i] != ll[count])
1591 {
1592 gnss->dataflags2[num] |= cd.lock;
1593 handle->lastlockmsm[j][i] = ll[count];
1594 }
1595 gnss->dataflags[num] |= (1<<cd.typeP);
1596 }
1597
1598 gnss->measdata[num][cd.typeS] = cnr[count];
1599 gnss->dataflags[num] |= (1<<cd.typeS);
1600
1601 if(dop[count] > -1.6384)
1602 {
1603 gnss->measdata[num][cd.typeD] = -(dop[count]
1604 +rdop[numsat])/wl;
1605 gnss->dataflags[num] |= (1<<cd.typeD);
1606 }
1607 break;
1608 }
1609 }
1610 }
1611 }
1612 }
1613 if(!syncf && !old)
1614 {
1615 handle->Data = *gnss;
1616 memset(gnss, 0, sizeof(*gnss));
1617 }
1618 if(!syncf || old)
1619 {
1620 if(!wasnoamb) /* not RINEX compatible without */
1621 ret = 1;
1622 else
1623 ret = 2;
1624 }
1625#ifdef NO_RTCM3_MAIN
1626 else
1627 ret = type;
1628#endif /* NO_RTCM3_MAIN */
1629 }
1630 break;
1631 }
1632 }
1633 return ret;
1634}
1635
1636struct Header
1637{
1638 const char *version;
1639 const char *pgm;
1640 const char *marker;
1641 const char *markertype;
1642 const char *observer;
1643 const char *receiver;
1644 const char *antenna;
1645 const char *position;
1646 const char *antennaposition;
1647 const char *wavelength;
1648 const char *typesofobs; /* should not be modified outside */
1649 const char *typesofobsG; /* should not be modified outside */
1650 const char *typesofobsR; /* should not be modified outside */
1651 const char *typesofobsS; /* should not be modified outside */
1652 const char *typesofobsE; /* should not be modified outside */
1653 const char *typesofobsC; /* should not be modified outside */
1654 const char *typesofobsJ; /* should not be modified outside */
1655 const char *timeoffirstobs; /* should not be modified outside */
1656};
1657
1658#define MAXHEADERLINES 50
1659#define MAXHEADERBUFFERSIZE 4096
1660struct HeaderData
1661{
1662 union
1663 {
1664 struct Header named;
1665 const char *unnamed[MAXHEADERLINES];
1666 } data;
1667 int numheaders;
1668};
1669
1670void converttime(struct converttimeinfo *c, int week, int tow)
1671{
1672 int i, k, doy, j; /* temporary variables */
1673 j = week*(7*24*60*60) + tow + 5*24*60*60;
1674 for(i = 1980; j >= (k = (365+longyear(i,0))*24*60*60); ++i)
1675 j -= k;
1676 c->year = i;
1677 doy = 1+ (j / (24*60*60));
1678 j %= (24*60*60);
1679 c->hour = j / (60*60);
1680 j %= (60*60);
1681 c->minute = j / 60;
1682 c->second = j % 60;
1683 j = 0;
1684 for(i = 1; j + (k = months[i] + longyear(c->year,i)) < doy; ++i)
1685 j += k;
1686 c->month = i;
1687 c->day = doy - j;
1688}
1689
1690#ifndef NO_RTCM3_MAIN
1691void RTCM3Error(const char *fmt, ...)
1692{
1693 va_list v;
1694 va_start(v, fmt);
1695 vfprintf(stderr, fmt, v);
1696 va_end(v);
1697}
1698#endif
1699
1700void RTCM3Text(const char *fmt, ...)
1701{
1702 va_list v;
1703 va_start(v, fmt);
1704 vprintf(fmt, v);
1705 va_end(v);
1706}
1707
1708static void fixrevision(void)
1709{
1710 if(revisionstr[0] == '$')
1711 {
1712 char *a;
1713 int i=sizeof(RTCM3TORINEX_VERSION); /* set version to 1.<revision> */
1714 strcpy(revisionstr, RTCM3TORINEX_VERSION ".");
1715 for(a = revisionstr+11; *a && *a != ' '; ++a)
1716 revisionstr[i++] = *a;
1717 revisionstr[i] = 0;
1718 }
1719}
1720
1721static int HandleRunBy(char *buffer, int buffersize, const char **u,
1722int rinex3)
1723{
1724 const char *user;
1725 time_t t;
1726 struct tm * t2;
1727
1728#ifdef NO_RTCM3_MAIN
1729 fixrevision();
1730#endif
1731
1732 user= getenv("USER");
1733 if(!user) user = "";
1734 t = time(&t);
1735 t2 = gmtime(&t);
1736 if(u) *u = user;
1737 return 1+snprintf(buffer, buffersize,
1738 rinex3 ?
1739 "RTCM3TORINEX %-7.7s%-20.20s%04d%02d%02d %02d%02d%02d UTC "
1740 "PGM / RUN BY / DATE" :
1741 "RTCM3TORINEX %-7.7s%-20.20s%04d-%02d-%02d %02d:%02d "
1742 "PGM / RUN BY / DATE", revisionstr, user, 1900+t2->tm_year,
1743 t2->tm_mon+1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
1744}
1745
1746#ifdef NO_RTCM3_MAIN
1747#define NUMSTARTSKIP 1
1748#else
1749#define NUMSTARTSKIP 3
1750#endif
1751
1752void HandleHeader(struct RTCM3ParserData *Parser)
1753{
1754#ifdef NO_RTCM3_MAIN
1755 int i;
1756 if(Parser->allflags == 0)
1757 Parser->allflags = ~0;
1758 if(Parser->rinex3)
1759 {
1760#define CHECKFLAGSNEW(a, b, c) \
1761 if(Parser->allflags & GNSSDF_##b##DATA) \
1762 { \
1763 Parser->info[RTCM3_MSM_##a].flags[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSDF_##b##DATA; \
1764 Parser->info[RTCM3_MSM_##a].pos[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSENTRY_##b##DATA; \
1765 ++Parser->info[RTCM3_MSM_##a].numtypes; \
1766 }
1767
1768 CHECKFLAGSNEW(GPS, C1, C1C)
1769 CHECKFLAGSNEW(GPS, L1C, L1C)
1770 CHECKFLAGSNEW(GPS, D1C, D1C)
1771 CHECKFLAGSNEW(GPS, S1C, S1C)
1772 CHECKFLAGSNEW(GPS, P1, C1P)
1773 CHECKFLAGSNEW(GPS, L1P, L1P)
1774 CHECKFLAGSNEW(GPS, D1P, D1P)
1775 CHECKFLAGSNEW(GPS, S1P, S1P)
1776 CHECKFLAGSNEW(GPS, P2, C2P)
1777 CHECKFLAGSNEW(GPS, L2P, L2P)
1778 CHECKFLAGSNEW(GPS, D2P, D2P)
1779 CHECKFLAGSNEW(GPS, S2P, S2P)
1780 CHECKFLAGSNEW(GPS, C2, C2X)
1781 CHECKFLAGSNEW(GPS, L2C, L2X)
1782 CHECKFLAGSNEW(GPS, D2C, D2X)
1783 CHECKFLAGSNEW(GPS, S2C, S2X)
1784 CHECKFLAGSNEW(GLONASS, C1, C1C)
1785 CHECKFLAGSNEW(GLONASS, L1C, L1C)
1786 CHECKFLAGSNEW(GLONASS, D1C, D1C)
1787 CHECKFLAGSNEW(GLONASS, S1C, S1C)
1788 CHECKFLAGSNEW(GLONASS, P1, C1P)
1789 CHECKFLAGSNEW(GLONASS, L1P, L1P)
1790 CHECKFLAGSNEW(GLONASS, D1P, D1P)
1791 CHECKFLAGSNEW(GLONASS, S1P, S1P)
1792 CHECKFLAGSNEW(GLONASS, P2, C2P)
1793 CHECKFLAGSNEW(GLONASS, L2P, L2P)
1794 CHECKFLAGSNEW(GLONASS, D2P, D2P)
1795 CHECKFLAGSNEW(GLONASS, S2P, S2P)
1796 CHECKFLAGSNEW(GLONASS, C2, C2C)
1797 CHECKFLAGSNEW(GLONASS, L2C, L2C)
1798 CHECKFLAGSNEW(GLONASS, D2C, D2C)
1799 CHECKFLAGSNEW(GLONASS, S2C, S2C)
1800 }
1801 else
1802 {
1803#define CHECKFLAGS(a, b) \
1804 if(Parser->allflags & GNSSDF_##a##DATA) \
1805 { \
1806 if(data[RINEXENTRY_##b##DATA]) \
1807 { \
1808 Parser->info[RTCM3_MSM_GPS].flags[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
1809 Parser->info[RTCM3_MSM_GPS].pos[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
1810 } \
1811 else \
1812 { \
1813 Parser->flags[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSDF_##a##DATA; \
1814 Parser->pos[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSENTRY_##a##DATA; \
1815 data[RINEXENTRY_##b##DATA] = ++Parser->info[RTCM3_MSM_GPS].numtypes; \
1816 } \
1817 }
1818
1819 int data[RINEXENTRY_NUMBER];
1820 for(i = 0; i < RINEXENTRY_NUMBER; ++i) data[i] = 0;
1821
1822 CHECKFLAGS(C1,C1)
1823 CHECKFLAGS(C2,C2)
1824 CHECKFLAGS(P1,P1)
1825 CHECKFLAGS(P2,P2)
1826 CHECKFLAGS(L1C,L1)
1827 CHECKFLAGS(L1P,L1)
1828 CHECKFLAGS(L2C,L2)
1829 CHECKFLAGS(L2P,L2)
1830 CHECKFLAGS(D1C,D1)
1831 CHECKFLAGS(D1P,D1)
1832 CHECKFLAGS(D2C,D2)
1833 CHECKFLAGS(D2P,D2)
1834 CHECKFLAGS(S1C,S1)
1835 CHECKFLAGS(S1P,S1)
1836 CHECKFLAGS(S2C,S2)
1837 CHECKFLAGS(S2P,S2)
1838 CHECKFLAGS(C5,C5)
1839 CHECKFLAGS(L5,L5)
1840 CHECKFLAGS(D5,D5)
1841 CHECKFLAGS(S5,S5)
1842 CHECKFLAGS(C5AB,C8)
1843 CHECKFLAGS(L5AB,L8)
1844 CHECKFLAGS(D5AB,D8)
1845 CHECKFLAGS(S5AB,S8)
1846 CHECKFLAGS(C5B,C7)
1847 CHECKFLAGS(L5B,L7)
1848 CHECKFLAGS(D5B,D7)
1849 CHECKFLAGS(S5B,S7)
1850 CHECKFLAGS(C6,C6)
1851 CHECKFLAGS(L6,L6)
1852 CHECKFLAGS(D6,D6)
1853 CHECKFLAGS(S6,S6)
1854 }
1855#else /* NO_RTCM3_MAIN */
1856 struct HeaderData hdata;
1857 char thebuffer[MAXHEADERBUFFERSIZE];
1858 char *buffer = thebuffer;
1859 size_t buffersize = sizeof(thebuffer);
1860 int i;
1861
1862 memset(&hdata, 0, sizeof(hdata));
1863
1864 hdata.data.named.version = buffer;
1865 i = 1+snprintf(buffer, buffersize,
1866 "%9.2f OBSERVATION DATA M (Mixed)"
1867 " RINEX VERSION / TYPE", Parser->rinex3 ? 3.0 : 2.11);
1868 buffer += i; buffersize -= i;
1869
1870 {
1871 const char *str;
1872 hdata.data.named.pgm = buffer;
1873 i = HandleRunBy(buffer, buffersize, &str, Parser->rinex3);
1874 buffer += i; buffersize -= i;
1875 hdata.data.named.observer = buffer;
1876 i = 1+snprintf(buffer, buffersize,
1877 "%-20.20s "
1878 "OBSERVER / AGENCY", str);
1879 buffer += i; buffersize -= i;
1880 }
1881
1882 hdata.data.named.marker =
1883 "RTCM3TORINEX "
1884 "MARKER NAME";
1885
1886 hdata.data.named.markertype = !Parser->rinex3 ? 0 :
1887 "GEODETIC "
1888 "MARKER TYPE";
1889
1890 hdata.data.named.receiver =
1891 " "
1892 "REC # / TYPE / VERS";
1893
1894 hdata.data.named.antenna =
1895 " "
1896 "ANT # / TYPE";
1897
1898 hdata.data.named.position =
1899 " .0000 .0000 .0000 "
1900 "APPROX POSITION XYZ";
1901
1902 hdata.data.named.antennaposition =
1903 " .0000 .0000 .0000 "
1904 "ANTENNA: DELTA H/E/N";
1905
1906 hdata.data.named.wavelength = Parser->rinex3 ? 0 :
1907 " 1 1 "
1908 "WAVELENGTH FACT L1/2";
1909
1910 hdata.numheaders = 18;
1911
1912 if(Parser->rinex3)
1913 {
1914#define CHECKFLAGSNEW(a, b, c) \
1915 if(flags & GNSSDF_##b##DATA) \
1916 { \
1917 Parser->info[RTCM3_MSM_##a].flags[Parser->info[RTCM3_MSM_##a].numtypes] \
1918 = GNSSDF_##b##DATA; \
1919 Parser->info[RTCM3_MSM_##a].pos[Parser->info[RTCM3_MSM_##a].numtypes] \
1920 = GNSSENTRY_##b##DATA; \
1921 ++Parser->info[RTCM3_MSM_##a].numtypes; \
1922 if(Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]) \
1923 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " %-2.2s%c", #c,\
1924 Parser->info[RTCM3_MSM_##a].type[GNSSENTRY_##b##DATA]); \
1925 else \
1926 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " %-3s", #c); \
1927 tbufferpos += 4; \
1928 }
1929
1930 int flags = Parser->startflags;
1931 char tbuffer[6*RINEXENTRY_NUMBER+1];
1932 int tbufferpos = 0;
1933 for(i = 0; i < Parser->Data.numsats; ++i)
1934 flags |= Parser->Data.dataflags[i];
1935
1936 CHECKFLAGSNEW(SBAS, C1, C1C)
1937 CHECKFLAGSNEW(SBAS, L1C, L1C)
1938 CHECKFLAGSNEW(SBAS, D1C, D1C)
1939 CHECKFLAGSNEW(SBAS, S1C, S1C)
1940 CHECKFLAGSNEW(SBAS, P1, C1W)
1941 CHECKFLAGSNEW(SBAS, L1P, L1W)
1942 CHECKFLAGSNEW(SBAS, D1P, D1W)
1943 CHECKFLAGSNEW(SBAS, S1P, S1W)
1944 CHECKFLAGSNEW(SBAS, C5, C5)
1945 CHECKFLAGSNEW(SBAS, L5, L5)
1946 CHECKFLAGSNEW(SBAS, D5, D5)
1947 CHECKFLAGSNEW(SBAS, S5, S5)
1948
1949 hdata.data.named.typesofobsS = buffer;
1950 i = 1+snprintf(buffer, buffersize,
1951 "S %3d%-52.52s SYS / # / OBS TYPES", Parser->info[RTCM3_MSM_SBAS].numtypes, tbuffer);
1952 buffer += i; buffersize -= i;
1953
1954 tbufferpos = 0;
1955
1956 CHECKFLAGSNEW(GPS, C1, C1C)
1957 CHECKFLAGSNEW(GPS, L1C, L1C)
1958 CHECKFLAGSNEW(GPS, D1C, D1C)
1959 CHECKFLAGSNEW(GPS, S1C, S1C)
1960 CHECKFLAGSNEW(GPS, P1, C1W)
1961 CHECKFLAGSNEW(GPS, L1P, L1W)
1962 CHECKFLAGSNEW(GPS, D1P, D1W)
1963 CHECKFLAGSNEW(GPS, S1P, S1W)
1964 CHECKFLAGSNEW(GPS, C5, C5)
1965 CHECKFLAGSNEW(GPS, L5, L5)
1966 CHECKFLAGSNEW(GPS, D5, D5)
1967 CHECKFLAGSNEW(GPS, S5, S5)
1968 CHECKFLAGSNEW(GPS, P2, C2P)
1969 CHECKFLAGSNEW(GPS, L2P, L2P)
1970 CHECKFLAGSNEW(GPS, D2P, D2P)
1971 CHECKFLAGSNEW(GPS, S2P, S2P)
1972 CHECKFLAGSNEW(GPS, C2, C2X)
1973 CHECKFLAGSNEW(GPS, L2C, L2X)
1974 CHECKFLAGSNEW(GPS, D2C, D2X)
1975 CHECKFLAGSNEW(GPS, S2C, S2X)
1976 CHECKFLAGSNEW(GPS, C1N, C1)
1977 CHECKFLAGSNEW(GPS, L1N, L1)
1978 CHECKFLAGSNEW(GPS, D1N, D1)
1979 CHECKFLAGSNEW(GPS, S1N, S1)
1980
1981 hdata.data.named.typesofobsG = buffer;
1982 i = 1+snprintf(buffer, buffersize,
1983 "G %3d%-52.52s SYS / # / OBS TYPES", Parser->info[RTCM3_MSM_GPS].numtypes, tbuffer);
1984 if(Parser->info[RTCM3_MSM_GPS].numtypes>13)
1985 {
1986 i += snprintf(buffer+i-1, buffersize,
1987 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
1988 }
1989 buffer += i; buffersize -= i;
1990
1991 tbufferpos = 0;
1992
1993 CHECKFLAGSNEW(GLONASS, C1, C1C)
1994 CHECKFLAGSNEW(GLONASS, L1C, L1C)
1995 CHECKFLAGSNEW(GLONASS, D1C, D1C)
1996 CHECKFLAGSNEW(GLONASS, S1C, S1C)
1997 CHECKFLAGSNEW(GLONASS, P1, C1P)
1998 CHECKFLAGSNEW(GLONASS, L1P, L1P)
1999 CHECKFLAGSNEW(GLONASS, D1P, D1P)
2000 CHECKFLAGSNEW(GLONASS, S1P, S1P)
2001 CHECKFLAGSNEW(GLONASS, P2, C2P)
2002 CHECKFLAGSNEW(GLONASS, L2P, L2P)
2003 CHECKFLAGSNEW(GLONASS, D2P, D2P)
2004 CHECKFLAGSNEW(GLONASS, S2P, S2P)
2005 CHECKFLAGSNEW(GLONASS, C2, C2C)
2006 CHECKFLAGSNEW(GLONASS, L2C, L2C)
2007 CHECKFLAGSNEW(GLONASS, D2C, D2C)
2008 CHECKFLAGSNEW(GLONASS, S2C, S2C)
2009
2010 hdata.data.named.typesofobsR = buffer;
2011 i = 1+snprintf(buffer, buffersize,
2012 "R %3d%-52.52s SYS / # / OBS TYPES", Parser->info[RTCM3_MSM_GLONASS].numtypes, tbuffer);
2013 if(Parser->info[RTCM3_MSM_GLONASS].numtypes>13)
2014 {
2015 i += snprintf(buffer+i-1, buffersize,
2016 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
2017 }
2018 buffer += i; buffersize -= i;
2019
2020 tbufferpos = 0;
2021
2022 CHECKFLAGSNEW(GALILEO, C1, C1)
2023 CHECKFLAGSNEW(GALILEO, L1C, L1)
2024 CHECKFLAGSNEW(GALILEO, D1C, D1)
2025 CHECKFLAGSNEW(GALILEO, S1C, S1)
2026 CHECKFLAGSNEW(GALILEO, C6, C6)
2027 CHECKFLAGSNEW(GALILEO, L6, L6)
2028 CHECKFLAGSNEW(GALILEO, D6, D6)
2029 CHECKFLAGSNEW(GALILEO, S6, S6)
2030 CHECKFLAGSNEW(GALILEO, C5, C5)
2031 CHECKFLAGSNEW(GALILEO, L5, L5)
2032 CHECKFLAGSNEW(GALILEO, D5, D5)
2033 CHECKFLAGSNEW(GALILEO, S5, S5)
2034 CHECKFLAGSNEW(GALILEO, C5B, C7)
2035 CHECKFLAGSNEW(GALILEO, L5B, L7)
2036 CHECKFLAGSNEW(GALILEO, D5B, D7)
2037 CHECKFLAGSNEW(GALILEO, S5B, S7)
2038 CHECKFLAGSNEW(GALILEO, C5AB, C8)
2039 CHECKFLAGSNEW(GALILEO, L5AB, L8)
2040 CHECKFLAGSNEW(GALILEO, D5AB, D8)
2041 CHECKFLAGSNEW(GALILEO, S5AB, S8)
2042
2043 hdata.data.named.typesofobsE = buffer;
2044 i = 1+snprintf(buffer, buffersize,
2045 "E %3d%-52.52s SYS / # / OBS TYPES", Parser->info[RTCM3_MSM_GALILEO].numtypes, tbuffer);
2046 if(Parser->info[RTCM3_MSM_GALILEO].numtypes>13)
2047 {
2048 i += snprintf(buffer+i-1, buffersize,
2049 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
2050 }
2051 buffer += i; buffersize -= i;
2052
2053 tbufferpos = 0;
2054
2055 CHECKFLAGSNEW(COMPASS, CB1, C2I)
2056 CHECKFLAGSNEW(COMPASS, LB1, L2I)
2057 CHECKFLAGSNEW(COMPASS, DB1, D2I)
2058 CHECKFLAGSNEW(COMPASS, SB1, S2I)
2059 CHECKFLAGSNEW(COMPASS, CB2, C7I)
2060 CHECKFLAGSNEW(COMPASS, LB2, L7I)
2061 CHECKFLAGSNEW(COMPASS, DB2, D7I)
2062 CHECKFLAGSNEW(COMPASS, SB2, S7I)
2063 CHECKFLAGSNEW(COMPASS, CB3, C6I)
2064 CHECKFLAGSNEW(COMPASS, LB3, L6I)
2065 CHECKFLAGSNEW(COMPASS, DB3, D6I)
2066 CHECKFLAGSNEW(COMPASS, SB3, S6I)
2067
2068 hdata.data.named.typesofobsC = buffer;
2069 i = 1+snprintf(buffer, buffersize,
2070 "C %3d%-52.52s SYS / # / OBS TYPES", Parser->info[RTCM3_MSM_COMPASS].numtypes, tbuffer);
2071 if(Parser->info[RTCM3_MSM_COMPASS].numtypes>13)
2072 {
2073 i += snprintf(buffer+i-1, buffersize,
2074 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
2075 }
2076 buffer += i; buffersize -= i;
2077
2078 tbufferpos = 0;
2079
2080 CHECKFLAGSNEW(QZSS, C1, C1C)
2081 CHECKFLAGSNEW(QZSS, L1C, L1C)
2082 CHECKFLAGSNEW(QZSS, D1C, D1C)
2083 CHECKFLAGSNEW(QZSS, S1C, S1C)
2084
2085 CHECKFLAGSNEW(QZSS, CSAIF, C1Z)
2086 CHECKFLAGSNEW(QZSS, LSAIF, L1Z)
2087 CHECKFLAGSNEW(QZSS, DSAIF, D1Z)
2088 CHECKFLAGSNEW(QZSS, SSAIF, S1Z)
2089
2090 CHECKFLAGSNEW(QZSS, C1N, C1)
2091 CHECKFLAGSNEW(QZSS, L1N, L1)
2092 CHECKFLAGSNEW(QZSS, D1N, D1)
2093 CHECKFLAGSNEW(QZSS, S1N, S1)
2094
2095 CHECKFLAGSNEW(QZSS, C6, C6)
2096 CHECKFLAGSNEW(QZSS, L6, L6)
2097 CHECKFLAGSNEW(QZSS, D6, D6)
2098 CHECKFLAGSNEW(QZSS, S6, S6)
2099
2100 CHECKFLAGSNEW(QZSS, C2, C2)
2101 CHECKFLAGSNEW(QZSS, L2C, L2)
2102 CHECKFLAGSNEW(QZSS, D2C, D2)
2103 CHECKFLAGSNEW(QZSS, S2C, S2)
2104
2105 CHECKFLAGSNEW(QZSS, C5, C5)
2106 CHECKFLAGSNEW(QZSS, L5, L5)
2107 CHECKFLAGSNEW(QZSS, D5, D5)
2108 CHECKFLAGSNEW(QZSS, S5, S5)
2109
2110 hdata.data.named.typesofobsJ = buffer;
2111 i = 1+snprintf(buffer, buffersize,
2112 "J %3d%-52.52s SYS / # / OBS TYPES", Parser->info[RTCM3_MSM_QZSS].numtypes, tbuffer);
2113 if(Parser->info[RTCM3_MSM_QZSS].numtypes>13)
2114 {
2115 i += snprintf(buffer+i-1, buffersize,
2116 "\n %-52.52s SYS / # / OBS TYPES", tbuffer+13*4);
2117 }
2118 buffer += i; buffersize -= i;
2119 }
2120 else
2121 {
2122#define CHECKFLAGS(a, b) \
2123 if(flags & GNSSDF_##a##DATA) \
2124 { \
2125 if(data[RINEXENTRY_##b##DATA]) \
2126 { \
2127 Parser->info[RTCM3_MSM_GPS].flags[data[RINEXENTRY_##b##DATA]-1] = GNSSDF_##a##DATA; \
2128 Parser->info[RTCM3_MSM_GPS].pos[data[RINEXENTRY_##b##DATA]-1] = GNSSENTRY_##a##DATA; \
2129 } \
2130 else \
2131 { \
2132 Parser->flags[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSDF_##a##DATA; \
2133 Parser->pos[Parser->info[RTCM3_MSM_GPS].numtypes] = GNSSENTRY_##a##DATA; \
2134 data[RINEXENTRY_##b##DATA] = ++Parser->info[RTCM3_MSM_GPS].numtypes; \
2135 snprintf(tbuffer+tbufferpos, sizeof(tbuffer)-tbufferpos, " "#b); \
2136 tbufferpos += 6; \
2137 } \
2138 }
2139
2140 int flags = Parser->startflags;
2141 int data[RINEXENTRY_NUMBER];
2142 char tbuffer[6*RINEXENTRY_NUMBER+1];
2143 int tbufferpos = 0;
2144 for(i = 0; i < RINEXENTRY_NUMBER; ++i)
2145 data[i] = 0;
2146 for(i = 0; i < Parser->Data.numsats; ++i)
2147 flags |= Parser->Data.dataflags[i];
2148
2149 CHECKFLAGS(C1,C1)
2150 CHECKFLAGS(C2,C2)
2151 CHECKFLAGS(P1,P1)
2152 CHECKFLAGS(P2,P2)
2153 CHECKFLAGS(L1C,L1)
2154 CHECKFLAGS(L1P,L1)
2155 CHECKFLAGS(L2C,L2)
2156 CHECKFLAGS(L2P,L2)
2157 CHECKFLAGS(D1C,D1)
2158 CHECKFLAGS(D1P,D1)
2159 CHECKFLAGS(D2C,D2)
2160 CHECKFLAGS(D2P,D2)
2161 CHECKFLAGS(S1C,S1)
2162 CHECKFLAGS(S1P,S1)
2163 CHECKFLAGS(S2C,S2)
2164 CHECKFLAGS(S2P,S2)
2165 CHECKFLAGS(C5,C5)
2166 CHECKFLAGS(L5,L5)
2167 CHECKFLAGS(D5,D5)
2168 CHECKFLAGS(S5,S5)
2169 CHECKFLAGS(C5AB,C8)
2170 CHECKFLAGS(L5AB,L8)
2171 CHECKFLAGS(D5AB,D8)
2172 CHECKFLAGS(S5AB,S8)
2173 CHECKFLAGS(C5B,C7)
2174 CHECKFLAGS(L5B,L7)
2175 CHECKFLAGS(D5B,D7)
2176 CHECKFLAGS(S5B,S7)
2177 CHECKFLAGS(C6,C6)
2178 CHECKFLAGS(L6,L6)
2179 CHECKFLAGS(D6,D6)
2180 CHECKFLAGS(S6,S6)
2181 /* Skip C1N and SAIF for RINEX2! */
2182
2183 hdata.data.named.typesofobs = buffer;
2184 i = 1+snprintf(buffer, buffersize,
2185 "%6d%-54.54s# / TYPES OF OBSERV", Parser->info[RTCM3_MSM_GPS].numtypes, tbuffer);
2186 if(Parser->info[RTCM3_MSM_GPS].numtypes>9)
2187 {
2188 i += snprintf(buffer+i-1, buffersize,
2189 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
2190 }
2191 if(Parser->info[RTCM3_MSM_GPS].numtypes>18)
2192 {
2193 i += snprintf(buffer+i-1, buffersize,
2194 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+18*6);
2195 }
2196 buffer += i; buffersize -= i;
2197 }
2198
2199 {
2200 struct converttimeinfo cti;
2201 converttime(&cti, Parser->Data.week,
2202 (int)floor(Parser->Data.timeofweek/1000.0));
2203 hdata.data.named.timeoffirstobs = buffer;
2204 i = 1+snprintf(buffer, buffersize,
2205 " %4d %2d %2d %2d %2d %10.7f GPS "
2206 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
2207 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
2208
2209 buffer += i; buffersize -= i;
2210 }
2211
2212 if(Parser->headerfile)
2213 {
2214 FILE *fh;
2215 if((fh = fopen(Parser->headerfile, "r")))
2216 {
2217 size_t siz;
2218 char *lastblockstart;
2219 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
2220 {
2221 buffer[siz] = '\n';
2222 if(siz == buffersize)
2223 {
2224 RTCM3Error("Header file is too large. Only %d bytes read.",
2225 (int)siz);
2226 }
2227 /* scan the file line by line and enter the entries in the list */
2228 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
2229 /* overwrites entries, except for comments */
2230 lastblockstart = buffer;
2231 for(i = 0; i < (int)siz; ++i)
2232 {
2233 if(buffer[i] == '\n')
2234 { /* we found a line */
2235 char *end;
2236 while(buffer[i+1] == '\r')
2237 ++i; /* skip \r in case there are any */
2238 end = buffer+i;
2239 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
2240 *(end--) = 0;
2241 if(end-lastblockstart < 60+5) /* short line */
2242 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
2243 else
2244 {
2245 int pos;
2246 if(!strcmp("COMMENT", lastblockstart+60))
2247 pos = hdata.numheaders;
2248 else
2249 {
2250 for(pos = 0; pos < hdata.numheaders; ++pos)
2251 {
2252 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2253 break;
2254 }
2255 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2256 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2257 {
2258 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2259 lastblockstart+60);
2260 }
2261 }
2262 if(pos >= MAXHEADERLINES)
2263 {
2264 RTCM3Error("Maximum number of header lines of %d reached.\n",
2265 MAXHEADERLINES);
2266 }
2267 else if(!strcmp("END OF HEADER", lastblockstart+60))
2268 {
2269 RTCM3Error("End of header ignored.\n");
2270 }
2271 else
2272 {
2273 hdata.data.unnamed[pos] = lastblockstart;
2274 if(pos == hdata.numheaders)
2275 ++hdata.numheaders;
2276 }
2277 }
2278 lastblockstart = buffer+i+1;
2279 }
2280 }
2281 }
2282 else
2283 {
2284 RTCM3Error("Could not read data from headerfile '%s'.\n",
2285 Parser->headerfile);
2286 }
2287 fclose(fh);
2288 }
2289 else
2290 {
2291 RTCM3Error("Could not open header datafile '%s'.\n",
2292 Parser->headerfile);
2293 }
2294 }
2295
2296 for(i = 0; i < hdata.numheaders; ++i)
2297 {
2298 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2299 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2300 }
2301 RTCM3Text(" "
2302 "END OF HEADER\n");
2303#endif
2304}
2305
2306static void ConvLine(FILE *file, const char *fmt, ...)
2307{
2308 char buffer[100], *b;
2309 va_list v;
2310 va_start(v, fmt);
2311 vsnprintf(buffer, sizeof(buffer), fmt, v);
2312 for(b = buffer; *b; ++b)
2313 {
2314 if(*b == 'e') *b = 'D';
2315 }
2316 fprintf(file, "%s", buffer);
2317 va_end(v);
2318}
2319
2320void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2321{
2322 Parser->Message[Parser->MessageSize++] = byte;
2323 if(Parser->MessageSize >= Parser->NeedBytes)
2324 {
2325 int r;
2326 while((r = RTCM3Parser(Parser)))
2327 {
2328 if(r == 1020 || r == 1019)
2329 {
2330 FILE *file = 0;
2331
2332 if(Parser->rinex3 && !(file = Parser->gpsfile))
2333 {
2334 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
2335 if(n)
2336 {
2337 if(!(Parser->gpsfile = fopen(n, "w")))
2338 {
2339 RTCM3Error("Could not open ephemeris output file.\n");
2340 }
2341 else
2342 {
2343 char buffer[100];
2344 fprintf(Parser->gpsfile,
2345 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2346 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2347 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2348 }
2349 Parser->gpsephemeris = 0;
2350 Parser->glonassephemeris = 0;
2351 file = Parser->gpsfile;
2352 }
2353 }
2354 else
2355 {
2356 if(r == 1020)
2357 {
2358 if(Parser->glonassephemeris)
2359 {
2360 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2361 {
2362 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2363 }
2364 else
2365 {
2366 char buffer[100];
2367 fprintf(Parser->glonassfile,
2368 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2369 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2370 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2371 }
2372 Parser->glonassephemeris = 0;
2373 }
2374 file = Parser->glonassfile;
2375 }
2376 else if(r == 1019)
2377 {
2378 if(Parser->gpsephemeris)
2379 {
2380 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2381 {
2382 RTCM3Error("Could not open GPS ephemeris output file.\n");
2383 }
2384 else
2385 {
2386 char buffer[100];
2387 fprintf(Parser->gpsfile,
2388 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2389 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2390 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2391 }
2392 Parser->gpsephemeris = 0;
2393 }
2394 file = Parser->gpsfile;
2395 }
2396 }
2397 if(file)
2398 {
2399 if(r == 1020)
2400 {
2401 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2402 int w = e->GPSWeek, tow = e->GPSTOW, i;
2403 struct converttimeinfo cti;
2404
2405 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2406 converttime(&cti, w, tow);
2407
2408 i = e->tk-3*60*60; if(i < 0) i += 86400;
2409
2410 if(Parser->rinex3)
2411 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2412 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2413 cti.second, -e->tau, e->gamma, (double) i);
2414 else
2415 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2416 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2417 (double) cti.second, -e->tau, e->gamma, (double) i);
2418 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
2419 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2420 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
2421 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2422 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
2423 e->z_velocity, e->z_acceleration, (double) e->E);
2424 }
2425 else /* if(r == 1019) */
2426 {
2427 struct gpsephemeris *e = &Parser->ephemerisGPS;
2428 double d; /* temporary variable */
2429 unsigned long int i; /* temporary variable */
2430 struct converttimeinfo cti;
2431 converttime(&cti, e->GPSweek, e->TOC);
2432
2433 if(Parser->rinex3)
2434 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2435 e->satellite, cti.year, cti.month, cti.day, cti.hour,
2436 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2437 e->clock_driftrate);
2438 else
2439 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2440 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
2441 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2442 e->clock_driftrate);
2443 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
2444 e->Crs, e->Delta_n, e->M0);
2445 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
2446 e->e, e->Cus, e->sqrt_A);
2447 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
2448 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2449 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
2450 e->Crc, e->omega, e->OMEGADOT);
2451 d = 0;
2452 i = e->flags;
2453 if(i & GPSEPHF_L2CACODE)
2454 d += 2.0;
2455 if(i & GPSEPHF_L2PCODE)
2456 d += 1.0;
2457 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
2458 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2459 if(e->URAindex <= 6) /* URA index */
2460 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2461 else
2462 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2463 /* 15 indicates not to use satellite. We can't handle this special
2464 case, so we create a high "non"-accuracy value. */
2465 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
2466 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2467
2468 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
2469 /* TOW */
2470 }
2471 }
2472 }
2473 else if (r == 1 || r == 2)
2474 {
2475 int i, j, o;
2476 struct converttimeinfo cti;
2477
2478 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
2479 {
2480 ++Parser->init;
2481
2482 if(Parser->init == NUMSTARTSKIP)
2483 HandleHeader(Parser);
2484 else
2485 {
2486 for(i = 0; i < Parser->Data.numsats; ++i)
2487 Parser->startflags |= Parser->Data.dataflags[i];
2488 continue;
2489 }
2490 }
2491 if(r == 2 && !Parser->validwarning)
2492 {
2493 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2494 " COMMENT\n");
2495 Parser->validwarning = 1;
2496 }
2497
2498 converttime(&cti, Parser->Data.week,
2499 (int)floor(Parser->Data.timeofweek/1000.0));
2500 if(Parser->rinex3)
2501 {
2502 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
2503 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2504 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2505 for(i = 0; i < Parser->Data.numsats; ++i)
2506 {
2507 int sys[RTCM3_MSM_NUMSYS] = {0,0,0,0,0,0};
2508 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2509 {
2510 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2511 sys[RTCM3_MSM_GPS] = 1;
2512 }
2513 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2514 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2515 {
2516 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2517 sys[RTCM3_MSM_GLONASS] = 1;
2518 }
2519 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2520 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2521 {
2522 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2523 sys[RTCM3_MSM_GALILEO] = 1;
2524 }
2525 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2526 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2527 {
2528 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2529 sys[RTCM3_MSM_GALILEO] = 1;
2530 }
2531 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2532 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2533 {
2534 RTCM3Text("J%02d", Parser->Data.satellites[i] - (PRN_QZSS_START-1));
2535 sys[RTCM3_MSM_QZSS] = 1;
2536 }
2537 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2538 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2539 {
2540 RTCM3Text("C%02d", Parser->Data.satellites[i] - (PRN_COMPASS_START-1));
2541 sys[RTCM3_MSM_COMPASS] = 1;
2542 }
2543 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2544 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2545 {
2546 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_SBAS_START+20);
2547 sys[RTCM3_MSM_SBAS] = 1;
2548 }
2549 else
2550 {
2551 RTCM3Text("%3d", Parser->Data.satellites[i]);
2552 }
2553
2554 if(sys[RTCM3_MSM_GLONASS])
2555 {
2556 for(j = 0; j < Parser->info[RTCM3_MSM_GLONASS].numtypes; ++j)
2557 {
2558 int df = Parser->info[RTCM3_MSM_GLONASS].flags[j];
2559 int pos = Parser->info[RTCM3_MSM_GLONASS].pos[j];
2560 if((Parser->Data.dataflags[i] & df)
2561 && !isnan(Parser->Data.measdata[i][pos])
2562 && !isinf(Parser->Data.measdata[i][pos])
2563 && (Parser->Data.codetype[i][pos]
2564 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
2565 && Parser->info[RTCM3_MSM_GLONASS].type[pos]
2566 == Parser->Data.codetype[i][pos][1]))
2567 {
2568 char lli = ' ';
2569 char snr = ' ';
2570 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2571 {
2572 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2573 lli = '1';
2574 snr = '0'+Parser->Data.snrL1[i];
2575 }
2576 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2577 {
2578 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2579 lli = '1';
2580 snr = '0'+Parser->Data.snrL2[i];
2581 }
2582 RTCM3Text("%14.3f%c%c",
2583 Parser->Data.measdata[i][pos],lli,snr);
2584 }
2585 else
2586 { /* no or illegal data */
2587 RTCM3Text(" ");
2588 }
2589 }
2590 }
2591 else if(sys[RTCM3_MSM_GALILEO])
2592 {
2593 for(j = 0; j < Parser->info[RTCM3_MSM_GALILEO].numtypes; ++j)
2594 {
2595 int df = Parser->info[RTCM3_MSM_GALILEO].flags[j];
2596 int pos = Parser->info[RTCM3_MSM_GALILEO].pos[j];
2597 if((Parser->Data.dataflags[i] & df)
2598 && !isnan(Parser->Data.measdata[i][pos])
2599 && !isinf(Parser->Data.measdata[i][pos])
2600 && (Parser->Data.codetype[i][pos]
2601 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
2602 && Parser->info[RTCM3_MSM_GALILEO].type[pos]
2603 == Parser->Data.codetype[i][pos][1]))
2604 {
2605 char lli = ' ';
2606 char snr = ' ';
2607 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2608 {
2609 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2610 lli = '1';
2611 snr = '0'+Parser->Data.snrL1[i];
2612 }
2613 if(df & GNSSDF_L6DATA)
2614 {
2615 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2616 lli = '1';
2617 snr = ' ';
2618 }
2619 if(df & GNSSDF_L5DATA)
2620 {
2621 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2622 lli = '1';
2623 snr = ' ';
2624 }
2625 if(df & GNSSDF_L5BDATA)
2626 {
2627 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2628 lli = '1';
2629 snr = ' ';
2630 }
2631 if(df & GNSSDF_L5ABDATA)
2632 {
2633 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2634 lli = '1';
2635 snr = ' ';
2636 }
2637 RTCM3Text("%14.3f%c%c",
2638 Parser->Data.measdata[i][pos],lli,snr);
2639 }
2640 else
2641 { /* no or illegal data */
2642 RTCM3Text(" ");
2643 }
2644 }
2645 }
2646 else if(sys[RTCM3_MSM_COMPASS])
2647 {
2648 for(j = 0; j < Parser->info[RTCM3_MSM_COMPASS].numtypes; ++j)
2649 {
2650 int df = Parser->info[RTCM3_MSM_COMPASS].flags[j];
2651 int pos = Parser->info[RTCM3_MSM_COMPASS].pos[j];
2652 if((Parser->Data.dataflags[i] & df)
2653 && !isnan(Parser->Data.measdata[i][pos])
2654 && !isinf(Parser->Data.measdata[i][pos])
2655 && (Parser->Data.codetype[i][pos]
2656 && Parser->info[RTCM3_MSM_COMPASS].type[pos]
2657 && Parser->info[RTCM3_MSM_COMPASS].type[pos]
2658 == Parser->Data.codetype[i][pos][1]))
2659 {
2660 char lli = ' ';
2661 char snr = ' ';
2662 if(df & GNSSDF_LB1DATA)
2663 {
2664 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB1)
2665 lli = '1';
2666 }
2667 if(df & GNSSDF_LB2DATA)
2668 {
2669 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB2)
2670 lli = '1';
2671 }
2672 if(df & GNSSDF_LB3DATA)
2673 {
2674 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB3)
2675 lli = '1';
2676 }
2677 RTCM3Text("%14.3f%c%c",
2678 Parser->Data.measdata[i][pos],lli,snr);
2679 }
2680 else
2681 { /* no or illegal data */
2682 RTCM3Text(" ");
2683 }
2684 }
2685 }
2686 else if(sys[RTCM3_MSM_QZSS])
2687 {
2688 for(j = 0; j < Parser->info[RTCM3_MSM_QZSS].numtypes; ++j)
2689 {
2690 int df = Parser->info[RTCM3_MSM_QZSS].flags[j];
2691 int pos = Parser->info[RTCM3_MSM_QZSS].pos[j];
2692 if((Parser->Data.dataflags[i] & df)
2693 && !isnan(Parser->Data.measdata[i][pos])
2694 && !isinf(Parser->Data.measdata[i][pos])
2695 && (Parser->Data.codetype[i][pos]
2696 && Parser->info[RTCM3_MSM_QZSS].type[pos]
2697 && Parser->info[RTCM3_MSM_QZSS].type[pos]
2698 == Parser->Data.codetype[i][pos][1]))
2699 {
2700 char lli = ' ';
2701 char snr = ' ';
2702 if(df & GNSSDF_L1CDATA)
2703 {
2704 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2705 lli = '1';
2706 snr = '0'+Parser->Data.snrL1[i];
2707 }
2708 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2709 {
2710 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2711 lli = '1';
2712 snr = '0'+Parser->Data.snrL2[i];
2713 }
2714 if(df & GNSSDF_L5DATA)
2715 {
2716 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2717 lli = '1';
2718 snr = ' ';
2719 }
2720 RTCM3Text("%14.3f%c%c",
2721 Parser->Data.measdata[i][pos],lli,snr);
2722 }
2723 else
2724 { /* no or illegal data */
2725 RTCM3Text(" ");
2726 }
2727 }
2728 }
2729 else if(sys[RTCM3_MSM_SBAS])
2730 {
2731 for(j = 0; j < Parser->info[RTCM3_MSM_SBAS].numtypes; ++j)
2732 {
2733 int df = Parser->info[RTCM3_MSM_SBAS].flags[j];
2734 int pos = Parser->info[RTCM3_MSM_SBAS].pos[j];
2735 if((Parser->Data.dataflags[i] & df)
2736 && !isnan(Parser->Data.measdata[i][pos])
2737 && !isinf(Parser->Data.measdata[i][pos])
2738 && (Parser->Data.codetype[i][pos]
2739 && Parser->info[RTCM3_MSM_SBAS].type[pos]
2740 && Parser->info[RTCM3_MSM_SBAS].type[pos]
2741 == Parser->Data.codetype[i][pos][1]))
2742 {
2743 char lli = ' ';
2744 char snr = ' ';
2745 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2746 {
2747 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2748 lli = '1';
2749 snr = '0'+Parser->Data.snrL1[i];
2750 }
2751 if(df & GNSSDF_L5DATA)
2752 {
2753 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2754 lli = '1';
2755 snr = ' ';
2756 }
2757 RTCM3Text("%14.3f%c%c",
2758 Parser->Data.measdata[i][pos],lli,snr);
2759 }
2760 else
2761 { /* no or illegal data */
2762 RTCM3Text(" ");
2763 }
2764 }
2765 }
2766 else
2767 {
2768 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
2769 {
2770 int df = Parser->info[RTCM3_MSM_GPS].flags[j];
2771 int pos = Parser->info[RTCM3_MSM_GPS].pos[j];
2772 if((Parser->Data.dataflags[pos] & df)
2773 && !isnan(Parser->Data.measdata[i][pos])
2774 && !isinf(Parser->Data.measdata[i][pos])
2775 && (Parser->Data.codetype[i][pos]
2776 && Parser->info[RTCM3_MSM_GPS].type[pos]
2777 && Parser->info[RTCM3_MSM_GPS].type[pos]
2778 == Parser->Data.codetype[i][pos][1]))
2779 {
2780 char lli = ' ';
2781 char snr = ' ';
2782 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2783 {
2784 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2785 lli = '1';
2786 snr = '0'+Parser->Data.snrL1[i];
2787 }
2788 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2789 {
2790 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2791 lli = '1';
2792 snr = '0'+Parser->Data.snrL2[i];
2793 }
2794 if(df & GNSSDF_L5DATA)
2795 {
2796 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2797 lli = '1';
2798 snr = ' ';
2799 }
2800 RTCM3Text("%14.3f%c%c",
2801 Parser->Data.measdata[i][pos],lli,snr);
2802 }
2803 else
2804 { /* no or illegal data */
2805 RTCM3Text(" ");
2806 }
2807 }
2808 }
2809 RTCM3Text("\n");
2810 }
2811 }
2812 else
2813 {
2814 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
2815 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
2816 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2817 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
2818 {
2819 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2820 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2821 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2822 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2823 RTCM3Text("R%02d", Parser->Data.satellites[i]
2824 - (PRN_GLONASS_START-1));
2825 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2826 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2827 RTCM3Text("S%02d", Parser->Data.satellites[i]
2828 - PRN_SBAS_START+20);
2829 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2830 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2831 RTCM3Text("E%02d", Parser->Data.satellites[i]
2832 - (PRN_GALILEO_START-1));
2833 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2834 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2835 RTCM3Text("E%02d", Parser->Data.satellites[i]
2836 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2837 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2838 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2839 RTCM3Text("J%02d", Parser->Data.satellites[i]
2840 - (PRN_QZSS_START-1));
2841 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2842 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2843 RTCM3Text("C%02d", Parser->Data.satellites[i]
2844 - (PRN_COMPASS_START-1));
2845 else
2846 RTCM3Text("%3d", Parser->Data.satellites[i]);
2847 }
2848 RTCM3Text("\n");
2849 o = 12;
2850 j = Parser->Data.numsats - 12;
2851 while(j > 0)
2852 {
2853 RTCM3Text(" ");
2854 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
2855 {
2856 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2857 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2858 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2859 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2860 RTCM3Text("R%02d", Parser->Data.satellites[i]
2861 - (PRN_GLONASS_START-1));
2862 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2863 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2864 RTCM3Text("S%02d", Parser->Data.satellites[i]
2865 - PRN_SBAS_START+20);
2866 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2867 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2868 RTCM3Text("E%02d", Parser->Data.satellites[i]
2869 - (PRN_GALILEO_START-1));
2870 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2871 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2872 RTCM3Text("E%02d", Parser->Data.satellites[i]
2873 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2874 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2875 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2876 RTCM3Text("J%02d", Parser->Data.satellites[i]
2877 - (PRN_QZSS_START-1));
2878 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2879 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2880 RTCM3Text("C%02d", Parser->Data.satellites[i]
2881 - (PRN_COMPASS_START-1));
2882 else
2883 RTCM3Text("%3d", Parser->Data.satellites[i]);
2884 }
2885 RTCM3Text("\n");
2886 j -= 12;
2887 o += 12;
2888 }
2889 for(i = 0; i < Parser->Data.numsats; ++i)
2890 {
2891 for(j = 0; j < Parser->info[RTCM3_MSM_GPS].numtypes; ++j)
2892 {
2893 int v = 0;
2894 int df = Parser->flags[j];
2895 int pos = Parser->pos[j];
2896 if((Parser->Data.dataflags[i] & df)
2897 && !isnan(Parser->Data.measdata[i][pos])
2898 && !isinf(Parser->Data.measdata[i][pos]))
2899 {
2900 v = 1;
2901 }
2902 else
2903 {
2904 df = Parser->info[RTCM3_MSM_GPS].flags[j];
2905 pos = Parser->info[RTCM3_MSM_GPS].pos[j];
2906
2907 if((Parser->Data.dataflags[i] & df)
2908 && !isnan(Parser->Data.measdata[i][pos])
2909 && !isinf(Parser->Data.measdata[i][pos]))
2910 {
2911 v = 1;
2912 }
2913 }
2914
2915 if(!v)
2916 { /* no or illegal data */
2917 RTCM3Text(" ");
2918 }
2919 else
2920 {
2921 char lli = ' ';
2922 char snr = ' ';
2923 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2924 {
2925 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2926 lli = '1';
2927 snr = '0'+Parser->Data.snrL1[i];
2928 }
2929 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2930 {
2931 if(Parser->Data.dataflags2[i]
2932 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
2933 {
2934 lli = '0';
2935 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2936 lli += 1;
2937 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
2938 lli += 4;
2939 }
2940 snr = '0'+Parser->Data.snrL2[i];
2941 }
2942 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
2943 & GNSSDF2_XCORRL2))
2944 lli = '4';
2945 RTCM3Text("%14.3f%c%c",
2946 Parser->Data.measdata[i][pos],lli,snr);
2947 }
2948 if(j%5 == 4 || j == Parser->info[RTCM3_MSM_GPS].numtypes-1)
2949 RTCM3Text("\n");
2950 }
2951 }
2952 }
2953 }
2954 }
2955 }
2956}
2957
2958#ifndef NO_RTCM3_MAIN
2959static char datestr[] = "$Date: 2012-07-04 09:45:16 +0000 (Wed, 04 Jul 2012) $";
2960
2961/* The string, which is send as agent in HTTP request */
2962#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
2963
2964#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
2965
2966static const char encodingTable [64] = {
2967 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
2968 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
2969 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
2970 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
2971};
2972
2973/* does not buffer overrun, but breaks directly after an error */
2974/* returns the number of required bytes */
2975static int encode(char *buf, int size, const char *user, const char *pwd)
2976{
2977 unsigned char inbuf[3];
2978 char *out = buf;
2979 int i, sep = 0, fill = 0, bytes = 0;
2980
2981 while(*user || *pwd)
2982 {
2983 i = 0;
2984 while(i < 3 && *user) inbuf[i++] = *(user++);
2985 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
2986 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
2987 while(i < 3) {inbuf[i++] = 0; ++fill; }
2988 if(out-buf < size-1)
2989 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
2990 if(out-buf < size-1)
2991 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
2992 | ((inbuf [1] & 0xF0) >> 4)];
2993 if(out-buf < size-1)
2994 {
2995 if(fill == 2)
2996 *(out++) = '=';
2997 else
2998 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
2999 | ((inbuf [2] & 0xC0) >> 6)];
3000 }
3001 if(out-buf < size-1)
3002 {
3003 if(fill >= 1)
3004 *(out++) = '=';
3005 else
3006 *(out++) = encodingTable[inbuf [2] & 0x3F];
3007 }
3008 bytes += 4;
3009 }
3010 if(out-buf < size)
3011 *out = 0;
3012 return bytes;
3013}
3014
3015static int stop = 0;
3016
3017struct Args
3018{
3019 const char *server;
3020 const char *port;
3021 int mode;
3022 int timeout;
3023 int rinex3;
3024 const char *user;
3025 const char *password;
3026 const char *proxyhost;
3027 const char *proxyport;
3028 const char *nmea;
3029 const char *data;
3030 const char *headerfile;
3031 const char *gpsephemeris;
3032 const char *glonassephemeris;
3033};
3034
3035/* option parsing */
3036#ifdef NO_LONG_OPTS
3037#define LONG_OPT(a)
3038#else
3039#define LONG_OPT(a) a
3040static struct option opts[] = {
3041{ "data", required_argument, 0, 'd'},
3042{ "server", required_argument, 0, 's'},
3043{ "password", required_argument, 0, 'p'},
3044{ "port", required_argument, 0, 'r'},
3045{ "timeout", required_argument, 0, 't'},
3046{ "header", required_argument, 0, 'f'},
3047{ "user", required_argument, 0, 'u'},
3048{ "gpsephemeris", required_argument, 0, 'E'},
3049{ "glonassephemeris", required_argument, 0, 'G'},
3050{ "rinex3", no_argument, 0, '3'},
3051{ "proxyport", required_argument, 0, 'R'},
3052{ "proxyhost", required_argument, 0, 'S'},
3053{ "nmea", required_argument, 0, 'n'},
3054{ "mode", required_argument, 0, 'M'},
3055{ "help", no_argument, 0, 'h'},
3056{0,0,0,0}};
3057#endif
3058#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
3059
3060enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
3061
3062static const char *geturl(const char *url, struct Args *args)
3063{
3064 static char buf[1000];
3065 static char *Buffer = buf;
3066 static char *Bufend = buf+sizeof(buf);
3067
3068 if(strncmp("ntrip:", url, 6))
3069 return "URL must start with 'ntrip:'.";
3070 url += 6; /* skip ntrip: */
3071
3072 if(*url != '@' && *url != '/')
3073 {
3074 /* scan for mountpoint */
3075 args->data = Buffer;
3076 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
3077 *(Buffer++) = *(url++);
3078 if(Buffer == args->data)
3079 return "Mountpoint required.";
3080 else if(Buffer >= Bufend-1)
3081 return "Parsing buffer too short.";
3082 *(Buffer++) = 0;
3083 }
3084
3085 if(*url == '/') /* username and password */
3086 {
3087 ++url;
3088 args->user = Buffer;
3089 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
3090 *(Buffer++) = *(url++);
3091 if(Buffer == args->user)
3092 return "Username cannot be empty.";
3093 else if(Buffer >= Bufend-1)
3094 return "Parsing buffer too short.";
3095 *(Buffer++) = 0;
3096
3097 if(*url == ':') ++url;
3098
3099 args->password = Buffer;
3100 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3101 *(Buffer++) = *(url++);
3102 if(Buffer == args->password)
3103 return "Password cannot be empty.";
3104 else if(Buffer >= Bufend-1)
3105 return "Parsing buffer too short.";
3106 *(Buffer++) = 0;
3107 }
3108
3109 if(*url == '@') /* server */
3110 {
3111 ++url;
3112 if(*url != '@' && *url != ':')
3113 {
3114 args->server = Buffer;
3115 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
3116 *(Buffer++) = *(url++);
3117 if(Buffer == args->server)
3118 return "Servername cannot be empty.";
3119 else if(Buffer >= Bufend-1)
3120 return "Parsing buffer too short.";
3121 *(Buffer++) = 0;
3122 }
3123
3124 if(*url == ':')
3125 {
3126 ++url;
3127 args->port = Buffer;
3128 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3129 *(Buffer++) = *(url++);
3130 if(Buffer == args->port)
3131 return "Port cannot be empty.";
3132 else if(Buffer >= Bufend-1)
3133 return "Parsing buffer too short.";
3134 *(Buffer++) = 0;
3135 }
3136
3137 if(*url == '@') /* proxy */
3138 {
3139 ++url;
3140 args->proxyhost = Buffer;
3141 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
3142 *(Buffer++) = *(url++);
3143 if(Buffer == args->proxyhost)
3144 return "Proxy servername cannot be empty.";
3145 else if(Buffer >= Bufend-1)
3146 return "Parsing buffer too short.";
3147 *(Buffer++) = 0;
3148
3149 if(*url == ':')
3150 {
3151 ++url;
3152 args->proxyport = Buffer;
3153 while(*url && *url != ';' && Buffer != Bufend)
3154 *(Buffer++) = *(url++);
3155 if(Buffer == args->proxyport)
3156 return "Proxy port cannot be empty.";
3157 else if(Buffer >= Bufend-1)
3158 return "Parsing buffer too short.";
3159 *(Buffer++) = 0;
3160 }
3161 }
3162 }
3163 if(*url == ';') /* NMEA */
3164 {
3165 args->nmea = ++url;
3166 while(*url)
3167 ++url;
3168 }
3169
3170 return *url ? "Garbage at end of server string." : 0;
3171}
3172
3173static int getargs(int argc, char **argv, struct Args *args)
3174{
3175 int res = 1;
3176 int getoptr;
3177 int help = 0;
3178 char *t;
3179
3180 args->server = "www.euref-ip.net";
3181 args->port = "2101";
3182 args->timeout = 60;
3183 args->user = "";
3184 args->password = "";
3185 args->data = 0;
3186 args->headerfile = 0;
3187 args->gpsephemeris = 0;
3188 args->glonassephemeris = 0;
3189 args->rinex3 = 0;
3190 args->nmea = 0;
3191 args->proxyhost = 0;
3192 args->proxyport = "2101";
3193 args->mode = AUTO;
3194 help = 0;
3195
3196 do
3197 {
3198
3199#ifdef NO_LONG_OPTS
3200 switch((getoptr = getopt(argc, argv, ARGOPT)))
3201#else
3202 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
3203#endif
3204 {
3205 case 's': args->server = optarg; break;
3206 case 'u': args->user = optarg; break;
3207 case 'p': args->password = optarg; break;
3208 case 'd': args->data = optarg; break;
3209 case 'f': args->headerfile = optarg; break;
3210 case 'E': args->gpsephemeris = optarg; break;
3211 case 'G': args->glonassephemeris = optarg; break;
3212 case 'r': args->port = optarg; break;
3213 case '3': args->rinex3 = 1; break;
3214 case 'S': args->proxyhost = optarg; break;
3215 case 'n': args->nmea = optarg; break;
3216 case 'R': args->proxyport = optarg; break;
3217 case 'h': help=1; break;
3218 case 'M':
3219 args->mode = 0;
3220 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
3221 args->mode = NTRIP1;
3222 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
3223 args->mode = HTTP;
3224 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
3225 args->mode = RTSP;
3226 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
3227 args->mode = AUTO;
3228 else args->mode = atoi(optarg);
3229 if((args->mode == 0) || (args->mode >= END))
3230 {
3231 fprintf(stderr, "Mode %s unknown\n", optarg);
3232 res = 0;
3233 }
3234 break;
3235 case 't':
3236 args->timeout = strtoul(optarg, &t, 10);
3237 if((t && *t) || args->timeout < 0)
3238 res = 0;
3239 break;
3240
3241 case 1:
3242 {
3243 const char *err;
3244 if((err = geturl(optarg, args)))
3245 {
3246 RTCM3Error("%s\n\n", err);
3247 res = 0;
3248 }
3249 }
3250 break;
3251 case -1: break;
3252 }
3253 } while(getoptr != -1 || !res);
3254
3255 datestr[0] = datestr[7];
3256 datestr[1] = datestr[8];
3257 datestr[2] = datestr[9];
3258 datestr[3] = datestr[10];
3259 datestr[5] = datestr[12];
3260 datestr[6] = datestr[13];
3261 datestr[8] = datestr[15];
3262 datestr[9] = datestr[16];
3263 datestr[4] = datestr[7] = '-';
3264 datestr[10] = 0;
3265
3266 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
3267 {
3268 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
3269 "Please specify only one navigation file.\n");
3270 res = 0;
3271 }
3272 else if(!res || help)
3273 {
3274 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
3275 "\nUsage: %s -s server -u user ...\n"
3276 " -d " LONG_OPT("--data ") "the requested data set\n"
3277 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
3278 " -s " LONG_OPT("--server ") "the server name or address\n"
3279 " -p " LONG_OPT("--password ") "the login password\n"
3280 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
3281 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
3282 " -u " LONG_OPT("--user ") "the user name\n"
3283 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
3284 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
3285 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
3286 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
3287 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
3288 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
3289 " -M " LONG_OPT("--mode ") "mode for data request\n"
3290 " Valid modes are:\n"
3291 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
3292 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
3293 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
3294 " 4, a, auto automatic detection (default)\n"
3295 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
3296 , revisionstr, datestr, argv[0], argv[0]);
3297 exit(1);
3298 }
3299 return res;
3300}
3301
3302/* let the output complete a block if necessary */
3303static void signalhandler(int sig)
3304{
3305 if(!stop)
3306 {
3307 RTCM3Error("Stop signal number %d received. "
3308 "Trying to terminate gentle.\n", sig);
3309 stop = 1;
3310 alarm(1);
3311 }
3312}
3313
3314#ifndef WINDOWSVERSION
3315static void WaitMicro(int mic)
3316{
3317 struct timeval tv;
3318 tv.tv_sec = mic/1000000;
3319 tv.tv_usec = mic%1000000;
3320#ifdef DEBUG
3321 fprintf(stderr, "Waiting %d micro seconds\n", mic);
3322#endif
3323 select(0, 0, 0, 0, &tv);
3324}
3325#else /* WINDOWSVERSION */
3326void WaitMicro(int mic)
3327{
3328 Sleep(mic/1000);
3329}
3330#endif /* WINDOWSVERSION */
3331
3332#define ALARMTIME (2*60)
3333
3334/* for some reason we had to abort hard (maybe waiting for data */
3335#ifdef __GNUC__
3336static __attribute__ ((noreturn)) void signalhandler_alarm(
3337int sig __attribute__((__unused__)))
3338#else /* __GNUC__ */
3339static void signalhandler_alarm(int sig)
3340#endif /* __GNUC__ */
3341{
3342 RTCM3Error("Programm forcefully terminated.\n");
3343 exit(1);
3344}
3345
3346int main(int argc, char **argv)
3347{
3348 struct Args args;
3349 struct RTCM3ParserData Parser;
3350
3351 setbuf(stdout, 0);
3352 setbuf(stdin, 0);
3353 setbuf(stderr, 0);
3354
3355 fixrevision();
3356
3357 signal(SIGINT, signalhandler);
3358 signal(SIGALRM,signalhandler_alarm);
3359 signal(SIGQUIT,signalhandler);
3360 signal(SIGTERM,signalhandler);
3361 signal(SIGPIPE,signalhandler);
3362 memset(&Parser, 0, sizeof(Parser));
3363 {
3364 time_t tim;
3365 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
3366 Parser.GPSWeek = tim/(7*24*60*60);
3367 Parser.GPSTOW = tim%(7*24*60*60);
3368 }
3369
3370 if(getargs(argc, argv, &args))
3371 {
3372 int sockfd, numbytes;
3373 char buf[MAXDATASIZE];
3374 struct sockaddr_in their_addr; /* connector's address information */
3375 struct hostent *he;
3376 struct servent *se;
3377 const char *server, *port, *proxyserver = 0;
3378 char proxyport[6];
3379 char *b;
3380 long i;
3381 struct timeval tv;
3382
3383 alarm(ALARMTIME);
3384
3385 Parser.headerfile = args.headerfile;
3386 Parser.glonassephemeris = args.glonassephemeris;
3387 Parser.gpsephemeris = args.gpsephemeris;
3388 Parser.rinex3 = args.rinex3;
3389
3390 if(args.proxyhost)
3391 {
3392 int p;
3393 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
3394 p = i;
3395 else if(!(se = getservbyname(args.port, 0)))
3396 {
3397 RTCM3Error("Can't resolve port %s.", args.port);
3398 exit(1);
3399 }
3400 else
3401 {
3402 p = ntohs(se->s_port);
3403 }
3404 snprintf(proxyport, sizeof(proxyport), "%d", p);
3405 port = args.proxyport;
3406 proxyserver = args.server;
3407 server = args.proxyhost;
3408 }
3409 else
3410 {
3411 server = args.server;
3412 port = args.port;
3413 }
3414
3415 memset(&their_addr, 0, sizeof(struct sockaddr_in));
3416 if((i = strtol(port, &b, 10)) && (!b || !*b))
3417 their_addr.sin_port = htons(i);
3418 else if(!(se = getservbyname(port, 0)))
3419 {
3420 RTCM3Error("Can't resolve port %s.", port);
3421 exit(1);
3422 }
3423 else
3424 {
3425 their_addr.sin_port = se->s_port;
3426 }
3427 if(!(he=gethostbyname(server)))
3428 {
3429 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3430 exit(1);
3431 }
3432 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3433 {
3434 perror("socket");
3435 exit(1);
3436 }
3437
3438 tv.tv_sec = args.timeout;
3439 tv.tv_usec = 0;
3440 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3441 {
3442 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3443 exit(1);
3444 }
3445
3446 their_addr.sin_family = AF_INET;
3447 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3448
3449 if(args.data && args.mode == RTSP)
3450 {
3451 struct sockaddr_in local;
3452 int sockudp, localport;
3453 int cseq = 1;
3454 socklen_t len;
3455
3456 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3457 {
3458 perror("socket");
3459 exit(1);
3460 }
3461 /* fill structure with local address information for UDP */
3462 memset(&local, 0, sizeof(local));
3463 local.sin_family = AF_INET;
3464 local.sin_port = htons(0);
3465 local.sin_addr.s_addr = htonl(INADDR_ANY);
3466 len = sizeof(local);
3467 /* bind() in order to get a random RTP client_port */
3468 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3469 {
3470 perror("bind");
3471 exit(1);
3472 }
3473 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3474 {
3475 localport = ntohs(local.sin_port);
3476 }
3477 else
3478 {
3479 perror("local access failed");
3480 exit(1);
3481 }
3482 if(connect(sockfd, (struct sockaddr *)&their_addr,
3483 sizeof(struct sockaddr)) == -1)
3484 {
3485 perror("connect");
3486 exit(1);
3487 }
3488 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3489 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3490 "CSeq: %d\r\n"
3491 "Ntrip-Version: Ntrip/2.0\r\n"
3492 "Ntrip-Component: Ntripclient\r\n"
3493 "User-Agent: %s/%s\r\n"
3494 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3495 "Authorization: Basic ",
3496 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3497 args.data, cseq++, AGENTSTRING, revisionstr, localport);
3498 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3499 {
3500 RTCM3Error("Requested data too long\n");
3501 exit(1);
3502 }
3503 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3504 if(i > MAXDATASIZE-4)
3505 {
3506 RTCM3Error("Username and/or password too long\n");
3507 exit(1);
3508 }
3509 buf[i++] = '\r';
3510 buf[i++] = '\n';
3511 buf[i++] = '\r';
3512 buf[i++] = '\n';
3513 if(args.nmea)
3514 {
3515 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3516 if(j >= 0 && j < MAXDATASIZE-i)
3517 i += j;
3518 else
3519 {
3520 RTCM3Error("NMEA string too long\n");
3521 exit(1);
3522 }
3523 }
3524 if(send(sockfd, buf, (size_t)i, 0) != i)
3525 {
3526 perror("send");
3527 exit(1);
3528 }
3529 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3530 {
3531 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3532 {
3533 int serverport = 0, session = 0;
3534 const char *portcheck = "server_port=";
3535 const char *sessioncheck = "session: ";
3536 int l = strlen(portcheck)-1;
3537 int j=0;
3538 for(i = 0; j != l && i < numbytes-l; ++i)
3539 {
3540 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3541 ;
3542 }
3543 if(i == numbytes-l)
3544 {
3545 RTCM3Error("No server port number found\n");
3546 exit(1);
3547 }
3548 else
3549 {
3550 i+=l;
3551 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3552 serverport = serverport * 10 + buf[i++]-'0';
3553 if(buf[i] != '\r' && buf[i] != ';')
3554 {
3555 RTCM3Error("Could not extract server port\n");
3556 exit(1);
3557 }
3558 }
3559 l = strlen(sessioncheck)-1;
3560 j=0;
3561 for(i = 0; j != l && i < numbytes-l; ++i)
3562 {
3563 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3564 ;
3565 }
3566 if(i == numbytes-l)
3567 {
3568 RTCM3Error("No session number found\n");
3569 exit(1);
3570 }
3571 else
3572 {
3573 i+=l;
3574 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3575 session = session * 10 + buf[i++]-'0';
3576 if(buf[i] != '\r')
3577 {
3578 RTCM3Error("Could not extract session number\n");
3579 exit(1);
3580 }
3581 }
3582
3583 i = snprintf(buf, MAXDATASIZE,
3584 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3585 "CSeq: %d\r\n"
3586 "Session: %d\r\n"
3587 "\r\n",
3588 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3589 args.data, cseq++, session);
3590
3591 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3592 {
3593 RTCM3Error("Requested data too long\n");
3594 exit(1);
3595 }
3596 if(send(sockfd, buf, (size_t)i, 0) != i)
3597 {
3598 perror("send");
3599 exit(1);
3600 }
3601 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3602 {
3603 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3604 {
3605 struct sockaddr_in addrRTP;
3606 /* fill structure with caster address information for UDP */
3607 memset(&addrRTP, 0, sizeof(addrRTP));
3608 addrRTP.sin_family = AF_INET;
3609 addrRTP.sin_port = htons(serverport);
3610 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3611 len = sizeof(addrRTP);
3612 int ts = 0;
3613 int sn = 0;
3614 int ssrc = 0;
3615 int init = 0;
3616 int u, v, w;
3617 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3618 (struct sockaddr*) &addrRTP, &len)) > 0)
3619 {
3620 alarm(ALARMTIME);
3621 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3622 {
3623 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3624 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3625 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3626 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3627 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3628
3629 if(init)
3630 {
3631 int z;
3632 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3633 if(ssrc != w || ts > v)
3634 {
3635 RTCM3Error("Illegal UDP data received.\n");
3636 exit(1);
3637 }
3638 if(u > sn) /* don't show out-of-order packets */
3639 for(z = 12; z < i && !stop; ++z)
3640 HandleByte(&Parser, (unsigned int) buf[z]);
3641 }
3642 sn = u; ts = v; ssrc = w; init = 1;
3643 }
3644 else
3645 {
3646 RTCM3Error("Illegal UDP header.\n");
3647 exit(1);
3648 }
3649 }
3650 }
3651 i = snprintf(buf, MAXDATASIZE,
3652 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
3653 "CSeq: %d\r\n"
3654 "Session: %d\r\n"
3655 "\r\n",
3656 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3657 args.data, cseq++, session);
3658
3659 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3660 {
3661 RTCM3Error("Requested data too long\n");
3662 exit(1);
3663 }
3664 if(send(sockfd, buf, (size_t)i, 0) != i)
3665 {
3666 perror("send");
3667 exit(1);
3668 }
3669 }
3670 else
3671 {
3672 RTCM3Error("Could not start data stream.\n");
3673 exit(1);
3674 }
3675 }
3676 else
3677 {
3678 RTCM3Error("Could not setup initial control connection.\n");
3679 exit(1);
3680 }
3681 }
3682 else
3683 {
3684 perror("recv");
3685 exit(1);
3686 }
3687 }
3688 else
3689 {
3690 if(connect(sockfd, (struct sockaddr *)&their_addr,
3691 sizeof(struct sockaddr)) == -1)
3692 {
3693 perror("connect");
3694 exit(1);
3695 }
3696 if(!args.data)
3697 {
3698 i = snprintf(buf, MAXDATASIZE,
3699 "GET %s%s%s%s/ HTTP/1.0\r\n"
3700 "Host: %s\r\n%s"
3701 "User-Agent: %s/%s\r\n"
3702 "Connection: close\r\n"
3703 "\r\n"
3704 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3705 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3706 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3707 AGENTSTRING, revisionstr);
3708 }
3709 else
3710 {
3711 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3712 "GET %s%s%s%s/%s HTTP/1.0\r\n"
3713 "Host: %s\r\n%s"
3714 "User-Agent: %s/%s\r\n"
3715 "Connection: close\r\n"
3716 "Authorization: Basic "
3717 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3718 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3719 args.data, args.server,
3720 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3721 AGENTSTRING, revisionstr);
3722 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3723 {
3724 RTCM3Error("Requested data too long\n");
3725 exit(1);
3726 }
3727 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3728 if(i > MAXDATASIZE-4)
3729 {
3730 RTCM3Error("Username and/or password too long\n");
3731 exit(1);
3732 }
3733 buf[i++] = '\r';
3734 buf[i++] = '\n';
3735 buf[i++] = '\r';
3736 buf[i++] = '\n';
3737 if(args.nmea)
3738 {
3739 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3740 if(j >= 0 && j < MAXDATASIZE-i)
3741 i += j;
3742 else
3743 {
3744 RTCM3Error("NMEA string too long\n");
3745 exit(1);
3746 }
3747 }
3748 }
3749 if(send(sockfd, buf, (size_t)i, 0) != i)
3750 {
3751 perror("send");
3752 exit(1);
3753 }
3754 if(args.data)
3755 {
3756 int k = 0;
3757 int chunkymode = 0;
3758 int starttime = time(0);
3759 int lastout = starttime;
3760 int totalbytes = 0;
3761 int chunksize = 0;
3762
3763 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3764 {
3765 if(numbytes > 0)
3766 alarm(ALARMTIME);
3767 else
3768 {
3769 WaitMicro(100);
3770 continue;
3771 }
3772 if(!k)
3773 {
3774 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
3775 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
3776 {
3777 const char *datacheck = "Content-Type: gnss/data\r\n";
3778 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
3779 int l = strlen(datacheck)-1;
3780 int j=0;
3781 for(i = 0; j != l && i < numbytes-l; ++i)
3782 {
3783 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
3784 ;
3785 }
3786 if(i == numbytes-l)
3787 {
3788 RTCM3Error("No 'Content-Type: gnss/data' found\n");
3789 exit(1);
3790 }
3791 l = strlen(chunkycheck)-1;
3792 j=0;
3793 for(i = 0; j != l && i < numbytes-l; ++i)
3794 {
3795 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
3796 ;
3797 }
3798 if(i < numbytes-l)
3799 chunkymode = 1;
3800 }
3801 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
3802 {
3803 RTCM3Error("Could not get the requested data: ");
3804 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
3805 {
3806 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
3807 }
3808 RTCM3Error("\n");
3809 exit(1);
3810 }
3811 else if(args.mode != NTRIP1)
3812 {
3813 if(args.mode != AUTO)
3814 {
3815 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
3816 args.mode == AUTO ? ", falling back to NTRIP1" : "");
3817 }
3818 if(args.mode == HTTP)
3819 exit(1);
3820 }
3821 ++k;
3822 }
3823 else
3824 {
3825 if(chunkymode)
3826 {
3827 int stop = 0;
3828 int pos = 0;
3829 while(!stop && pos < numbytes)
3830 {
3831 switch(chunkymode)
3832 {
3833 case 1: /* reading number starts */
3834 chunksize = 0;
3835 ++chunkymode; /* no break */
3836 case 2: /* during reading number */
3837 i = buf[pos++];
3838 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
3839 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
3840 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
3841 else if(i == '\r') ++chunkymode;
3842 else if(i == ';') chunkymode = 5;
3843 else stop = 1;
3844 break;
3845 case 3: /* scanning for return */
3846 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
3847 else stop = 1;
3848 break;
3849 case 4: /* output data */
3850 i = numbytes-pos;
3851 if(i > chunksize) i = chunksize;
3852 {
3853 int z;
3854 for(z = 0; z < i && !stop; ++z)
3855 HandleByte(&Parser, (unsigned int) buf[pos+z]);
3856 }
3857 totalbytes += i;
3858 chunksize -= i;
3859 pos += i;
3860 if(!chunksize)
3861 chunkymode = 1;
3862 break;
3863 case 5:
3864 if(i == '\r') chunkymode = 3;
3865 break;
3866 }
3867 }
3868 if(stop)
3869 {
3870 RTCM3Error("Error in chunky transfer encoding\n");
3871 break;
3872 }
3873 }
3874 else
3875 {
3876 totalbytes += numbytes;
3877 {
3878 int z;
3879 for(z = 0; z < numbytes && !stop; ++z)
3880 HandleByte(&Parser, (unsigned int) buf[z]);
3881 }
3882 }
3883 if(totalbytes < 0) /* overflow */
3884 {
3885 totalbytes = 0;
3886 starttime = time(0);
3887 lastout = starttime;
3888 }
3889 }
3890 }
3891 }
3892 else
3893 {
3894 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
3895 {
3896 alarm(ALARMTIME);
3897 fwrite(buf, (size_t)numbytes, 1, stdout);
3898 }
3899 }
3900 close(sockfd);
3901 }
3902 }
3903 return 0;
3904}
3905#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.