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

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

fix BNC interface

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