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

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

reenable some galileo types

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