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

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

fix typo

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