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

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

first set of changes for better multiplattform support

  • 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 4367 2012-06-28 12:11:09Z 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: 4367 $";
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
2136 hdata.data.named.typesofobs = buffer;
2137 i = 1+snprintf(buffer, buffersize,
2138 "%6d%-54.54s# / TYPES OF OBSERV", Parser->numdatatypesGPS, tbuffer);
2139 if(Parser->numdatatypesGPS>9)
2140 {
2141 i += snprintf(buffer+i-1, buffersize,
2142 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+9*6);
2143 }
2144 if(Parser->numdatatypesGPS>18)
2145 {
2146 i += snprintf(buffer+i-1, buffersize,
2147 "\n %-54.54s# / TYPES OF OBSERV", tbuffer+18*6);
2148 }
2149 buffer += i; buffersize -= i;
2150 }
2151
2152 {
2153 struct converttimeinfo cti;
2154 converttime(&cti, Parser->Data.week,
2155 (int)floor(Parser->Data.timeofweek/1000.0));
2156 hdata.data.named.timeoffirstobs = buffer;
2157 i = 1+snprintf(buffer, buffersize,
2158 " %4d %2d %2d %2d %2d %10.7f GPS "
2159 "TIME OF FIRST OBS", cti.year, cti.month, cti.day, cti.hour,
2160 cti.minute, cti.second + fmod(Parser->Data.timeofweek/1000.0,1.0));
2161
2162 buffer += i; buffersize -= i;
2163 }
2164
2165 if(Parser->headerfile)
2166 {
2167 FILE *fh;
2168 if((fh = fopen(Parser->headerfile, "r")))
2169 {
2170 size_t siz;
2171 char *lastblockstart;
2172 if((siz = fread(buffer, 1, buffersize-1, fh)) > 0)
2173 {
2174 buffer[siz] = '\n';
2175 if(siz == buffersize)
2176 {
2177 RTCM3Error("Header file is too large. Only %d bytes read.",
2178 (int)siz);
2179 }
2180 /* scan the file line by line and enter the entries in the list */
2181 /* warn for "# / TYPES OF OBSERV" and "TIME OF FIRST OBS" */
2182 /* overwrites entries, except for comments */
2183 lastblockstart = buffer;
2184 for(i = 0; i < (int)siz; ++i)
2185 {
2186 if(buffer[i] == '\n')
2187 { /* we found a line */
2188 char *end;
2189 while(buffer[i+1] == '\r')
2190 ++i; /* skip \r in case there are any */
2191 end = buffer+i;
2192 while(*end == '\t' || *end == ' ' || *end == '\r' || *end == '\n')
2193 *(end--) = 0;
2194 if(end-lastblockstart < 60+5) /* short line */
2195 RTCM3Error("Short Header line '%s' ignored.\n", lastblockstart);
2196 else
2197 {
2198 int pos;
2199 if(!strcmp("COMMENT", lastblockstart+60))
2200 pos = hdata.numheaders;
2201 else
2202 {
2203 for(pos = 0; pos < hdata.numheaders; ++pos)
2204 {
2205 if(!strcmp(hdata.data.unnamed[pos]+60, lastblockstart+60))
2206 break;
2207 }
2208 if(!strcmp("# / TYPES OF OBSERV", lastblockstart+60)
2209 || !strcmp("TIME OF FIRST OBS", lastblockstart+60))
2210 {
2211 RTCM3Error("Overwriting header '%s' is dangerous.\n",
2212 lastblockstart+60);
2213 }
2214 }
2215 if(pos >= MAXHEADERLINES)
2216 {
2217 RTCM3Error("Maximum number of header lines of %d reached.\n",
2218 MAXHEADERLINES);
2219 }
2220 else if(!strcmp("END OF HEADER", lastblockstart+60))
2221 {
2222 RTCM3Error("End of header ignored.\n");
2223 }
2224 else
2225 {
2226 hdata.data.unnamed[pos] = lastblockstart;
2227 if(pos == hdata.numheaders)
2228 ++hdata.numheaders;
2229 }
2230 }
2231 lastblockstart = buffer+i+1;
2232 }
2233 }
2234 }
2235 else
2236 {
2237 RTCM3Error("Could not read data from headerfile '%s'.\n",
2238 Parser->headerfile);
2239 }
2240 fclose(fh);
2241 }
2242 else
2243 {
2244 RTCM3Error("Could not open header datafile '%s'.\n",
2245 Parser->headerfile);
2246 }
2247 }
2248
2249 for(i = 0; i < hdata.numheaders; ++i)
2250 {
2251 if(hdata.data.unnamed[i] && hdata.data.unnamed[i][0])
2252 RTCM3Text("%s\n", hdata.data.unnamed[i]);
2253 }
2254 RTCM3Text(" "
2255 "END OF HEADER\n");
2256#endif
2257}
2258
2259static void ConvLine(FILE *file, const char *fmt, ...)
2260{
2261 char buffer[100], *b;
2262 va_list v;
2263 va_start(v, fmt);
2264 vsnprintf(buffer, sizeof(buffer), fmt, v);
2265 for(b = buffer; *b; ++b)
2266 {
2267 if(*b == 'e') *b = 'D';
2268 }
2269 fprintf(file, "%s", buffer);
2270 va_end(v);
2271}
2272
2273void HandleByte(struct RTCM3ParserData *Parser, unsigned int byte)
2274{
2275 Parser->Message[Parser->MessageSize++] = byte;
2276 if(Parser->MessageSize >= Parser->NeedBytes)
2277 {
2278 int r;
2279 while((r = RTCM3Parser(Parser)))
2280 {
2281 if(r == 1020 || r == 1019)
2282 {
2283 FILE *file = 0;
2284
2285 if(Parser->rinex3 && !(file = Parser->gpsfile))
2286 {
2287 const char *n = Parser->gpsephemeris ? Parser->gpsephemeris : Parser->glonassephemeris;
2288 if(n)
2289 {
2290 if(!(Parser->gpsfile = fopen(n, "w")))
2291 {
2292 RTCM3Error("Could not open ephemeris output file.\n");
2293 }
2294 else
2295 {
2296 char buffer[100];
2297 fprintf(Parser->gpsfile,
2298 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n", 3.0, "", "");
2299 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2300 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2301 }
2302 Parser->gpsephemeris = 0;
2303 Parser->glonassephemeris = 0;
2304 file = Parser->gpsfile;
2305 }
2306 }
2307 else
2308 {
2309 if(r == 1020)
2310 {
2311 if(Parser->glonassephemeris)
2312 {
2313 if(!(Parser->glonassfile = fopen(Parser->glonassephemeris, "w")))
2314 {
2315 RTCM3Error("Could not open GLONASS ephemeris output file.\n");
2316 }
2317 else
2318 {
2319 char buffer[100];
2320 fprintf(Parser->glonassfile,
2321 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n", 2.1, "", "");
2322 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2323 fprintf(Parser->glonassfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2324 }
2325 Parser->glonassephemeris = 0;
2326 }
2327 file = Parser->glonassfile;
2328 }
2329 else if(r == 1019)
2330 {
2331 if(Parser->gpsephemeris)
2332 {
2333 if(!(Parser->gpsfile = fopen(Parser->gpsephemeris, "w")))
2334 {
2335 RTCM3Error("Could not open GPS ephemeris output file.\n");
2336 }
2337 else
2338 {
2339 char buffer[100];
2340 fprintf(Parser->gpsfile,
2341 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.1, "", "");
2342 HandleRunBy(buffer, sizeof(buffer), 0, Parser->rinex3);
2343 fprintf(Parser->gpsfile, "%s\n%60sEND OF HEADER\n", buffer, "");
2344 }
2345 Parser->gpsephemeris = 0;
2346 }
2347 file = Parser->gpsfile;
2348 }
2349 }
2350 if(file)
2351 {
2352 if(r == 1020)
2353 {
2354 struct glonassephemeris *e = &Parser->ephemerisGLONASS;
2355 int w = e->GPSWeek, tow = e->GPSTOW, i;
2356 struct converttimeinfo cti;
2357
2358 updatetime(&w, &tow, e->tb*1000, 1); /* Moscow - > UTC */
2359 converttime(&cti, w, tow);
2360
2361 i = e->tk-3*60*60; if(i < 0) i += 86400;
2362
2363 if(Parser->rinex3)
2364 ConvLine(file, "R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2365 e->almanac_number, cti.year, cti.month, cti.day, cti.hour, cti.minute,
2366 cti.second, -e->tau, e->gamma, (double) i);
2367 else
2368 ConvLine(file, "%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
2369 e->almanac_number, cti.year%100, cti.month, cti.day, cti.hour, cti.minute,
2370 (double) cti.second, -e->tau, e->gamma, (double) i);
2371 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->x_pos,
2372 e->x_velocity, e->x_acceleration, (e->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
2373 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->y_pos,
2374 e->y_velocity, e->y_acceleration, (double) e->frequency_number);
2375 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->z_pos,
2376 e->z_velocity, e->z_acceleration, (double) e->E);
2377 }
2378 else /* if(r == 1019) */
2379 {
2380 struct gpsephemeris *e = &Parser->ephemerisGPS;
2381 double d; /* temporary variable */
2382 unsigned long int i; /* temporary variable */
2383 struct converttimeinfo cti;
2384 converttime(&cti, e->GPSweek, e->TOC);
2385
2386 if(Parser->rinex3)
2387 ConvLine(file, "G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
2388 e->satellite, cti.year, cti.month, cti.day, cti.hour,
2389 cti.minute, cti.second, e->clock_bias, e->clock_drift,
2390 e->clock_driftrate);
2391 else
2392 ConvLine(file, "%02d %02d %02d %02d %02d %02d%05.1f%19.12e%19.12e%19.12e\n",
2393 e->satellite, cti.year%100, cti.month, cti.day, cti.hour,
2394 cti.minute, (double) cti.second, e->clock_bias, e->clock_drift,
2395 e->clock_driftrate);
2396 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", (double)e->IODE,
2397 e->Crs, e->Delta_n, e->M0);
2398 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->Cuc,
2399 e->e, e->Cus, e->sqrt_A);
2400 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n",
2401 (double) e->TOE, e->Cic, e->OMEGA0, e->Cis);
2402 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->i0,
2403 e->Crc, e->omega, e->OMEGADOT);
2404 d = 0;
2405 i = e->flags;
2406 if(i & GPSEPHF_L2CACODE)
2407 d += 2.0;
2408 if(i & GPSEPHF_L2PCODE)
2409 d += 1.0;
2410 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", e->IDOT, d,
2411 (double) e->GPSweek, i & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
2412 if(e->URAindex <= 6) /* URA index */
2413 d = ceil(10.0*pow(2.0, 1.0+((double)e->URAindex)/2.0))/10.0;
2414 else
2415 d = ceil(10.0*pow(2.0, ((double)e->URAindex)/2.0))/10.0;
2416 /* 15 indicates not to use satellite. We can't handle this special
2417 case, so we create a high "non"-accuracy value. */
2418 ConvLine(file, " %19.12e%19.12e%19.12e%19.12e\n", d,
2419 ((double) e->SVhealth), e->TGD, ((double) e->IODC));
2420
2421 ConvLine(file, " %19.12e%19.12e\n", ((double)e->TOW), 0.0);
2422 /* TOW */
2423 }
2424 }
2425 }
2426 else if (r == 1 || r == 2)
2427 {
2428 int i, j, o;
2429 struct converttimeinfo cti;
2430
2431 if(Parser->init < NUMSTARTSKIP) /* skip first epochs to detect correct data types */
2432 {
2433 ++Parser->init;
2434
2435 if(Parser->init == NUMSTARTSKIP)
2436 HandleHeader(Parser);
2437 else
2438 {
2439 for(i = 0; i < Parser->Data.numsats; ++i)
2440 Parser->startflags |= Parser->Data.dataflags[i];
2441 continue;
2442 }
2443 }
2444 if(r == 2 && !Parser->validwarning)
2445 {
2446 RTCM3Text("No valid RINEX! All values are modulo 299792.458!"
2447 " COMMENT\n");
2448 Parser->validwarning = 1;
2449 }
2450
2451 converttime(&cti, Parser->Data.week,
2452 (int)floor(Parser->Data.timeofweek/1000.0));
2453 if(Parser->rinex3)
2454 {
2455 RTCM3Text("> %04d %02d %02d %02d %02d%11.7f 0%3d\n",
2456 cti.year, cti.month, cti.day, cti.hour, cti.minute, cti.second
2457 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2458 for(i = 0; i < Parser->Data.numsats; ++i)
2459 {
2460 int glo = 0, gal = 0, qzs = 0, com = 0;
2461 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2462 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2463 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2464 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2465 {
2466 RTCM3Text("R%02d", Parser->Data.satellites[i] - (PRN_GLONASS_START-1));
2467 glo = 1;
2468 }
2469 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2470 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2471 {
2472 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GALILEO_START-1));
2473 gal = 1;
2474 }
2475 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2476 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2477 {
2478 RTCM3Text("E%02d", Parser->Data.satellites[i] - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2479 gal = 1;
2480 }
2481 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2482 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2483 {
2484 RTCM3Text("J%02d", Parser->Data.satellites[i] - (PRN_QZSS_START-1));
2485 qzs = 1;
2486 }
2487 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2488 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2489 {
2490 RTCM3Text("C%02d", Parser->Data.satellites[i] - (PRN_COMPASS_START-1));
2491 com = 1;
2492 }
2493 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2494 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2495 RTCM3Text("S%02d", Parser->Data.satellites[i] - PRN_SBAS_START+20);
2496 else
2497 RTCM3Text("%3d", Parser->Data.satellites[i]);
2498
2499 if(glo)
2500 {
2501 for(j = 0; j < Parser->numdatatypesGLO; ++j)
2502 {
2503 int df = Parser->dataflagGLO[j];
2504 int pos = Parser->dataposGLO[j];
2505 if((Parser->Data.dataflags[i] & df)
2506 && !isnan(Parser->Data.measdata[i][pos])
2507 && !isinf(Parser->Data.measdata[i][pos]))
2508 {
2509 char lli = ' ';
2510 char snr = ' ';
2511 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2512 {
2513 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2514 lli = '1';
2515 snr = '0'+Parser->Data.snrL1[i];
2516 }
2517 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2518 {
2519 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2520 lli = '1';
2521 snr = '0'+Parser->Data.snrL2[i];
2522 }
2523 RTCM3Text("%14.3f%c%c",
2524 Parser->Data.measdata[i][pos],lli,snr);
2525 }
2526 else
2527 { /* no or illegal data */
2528 RTCM3Text(" ");
2529 }
2530 }
2531 }
2532 else if(gal)
2533 {
2534 for(j = 0; j < Parser->numdatatypesGAL; ++j)
2535 {
2536 int df = Parser->dataflagGAL[j];
2537 int pos = Parser->dataposGAL[j];
2538 if((Parser->Data.dataflags[i] & df)
2539 && !isnan(Parser->Data.measdata[i][pos])
2540 && !isinf(Parser->Data.measdata[i][pos]))
2541 {
2542 char lli = ' ';
2543 char snr = ' ';
2544 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2545 {
2546 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2547 lli = '1';
2548 snr = '0'+Parser->Data.snrL1[i];
2549 }
2550 if(df & GNSSDF_L6DATA)
2551 {
2552 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE6)
2553 lli = '1';
2554 snr = ' ';
2555 }
2556 if(df & GNSSDF_L5DATA)
2557 {
2558 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2559 lli = '1';
2560 snr = ' ';
2561 }
2562 if(df & GNSSDF_L5BDATA)
2563 {
2564 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5B)
2565 lli = '1';
2566 snr = ' ';
2567 }
2568 if(df & GNSSDF_L5ABDATA)
2569 {
2570 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSE5AB)
2571 lli = '1';
2572 snr = ' ';
2573 }
2574 RTCM3Text("%14.3f%c%c",
2575 Parser->Data.measdata[i][pos],lli,snr);
2576 }
2577 else
2578 { /* no or illegal data */
2579 RTCM3Text(" ");
2580 }
2581 }
2582 }
2583 else if(com)
2584 {
2585 for(j = 0; j < Parser->numdatatypesCOM; ++j)
2586 {
2587 int df = Parser->dataflagCOM[j];
2588 int pos = Parser->dataposCOM[j];
2589 if((Parser->Data.dataflags[i] & df)
2590 && !isnan(Parser->Data.measdata[i][pos])
2591 && !isinf(Parser->Data.measdata[i][pos]))
2592 {
2593 char lli = ' ';
2594 char snr = ' ';
2595 if(df & GNSSDF_LB1DATA)
2596 {
2597 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB1)
2598 lli = '1';
2599 }
2600 if(df & GNSSDF_LB2DATA)
2601 {
2602 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB2)
2603 lli = '1';
2604 }
2605 if(df & GNSSDF_LB3DATA)
2606 {
2607 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSB3)
2608 lli = '1';
2609 }
2610 RTCM3Text("%14.3f%c%c",
2611 Parser->Data.measdata[i][pos],lli,snr);
2612 }
2613 else
2614 { /* no or illegal data */
2615 RTCM3Text(" ");
2616 }
2617 }
2618 }
2619 else if(qzs)
2620 {
2621 for(j = 0; j < Parser->numdatatypesQZS; ++j)
2622 {
2623 int df = Parser->dataflagQZS[j];
2624 int pos = Parser->dataposQZS[j];
2625 if((Parser->Data.dataflags[i] & df)
2626 && !isnan(Parser->Data.measdata[i][pos])
2627 && !isinf(Parser->Data.measdata[i][pos]))
2628 {
2629 char lli = ' ';
2630 char snr = ' ';
2631 if(df & GNSSDF_L1CDATA)
2632 {
2633 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2634 lli = '1';
2635 snr = '0'+Parser->Data.snrL1[i];
2636 }
2637 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2638 {
2639 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2640 lli = '1';
2641 snr = '0'+Parser->Data.snrL2[i];
2642 }
2643 if(df & GNSSDF_L5DATA)
2644 {
2645 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2646 lli = '1';
2647 snr = ' ';
2648 }
2649 RTCM3Text("%14.3f%c%c",
2650 Parser->Data.measdata[i][pos],lli,snr);
2651 }
2652 else
2653 { /* no or illegal data */
2654 RTCM3Text(" ");
2655 }
2656 }
2657 }
2658 else
2659 {
2660 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2661 {
2662 int df = Parser->dataflagGPS[j];
2663 int pos = Parser->dataposGPS[j];
2664 if((Parser->Data.dataflags[i] & df)
2665 && !isnan(Parser->Data.measdata[i][pos])
2666 && !isinf(Parser->Data.measdata[i][pos]))
2667 {
2668 char lli = ' ';
2669 char snr = ' ';
2670 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2671 {
2672 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2673 lli = '1';
2674 snr = '0'+Parser->Data.snrL1[i];
2675 }
2676 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2677 {
2678 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2679 lli = '1';
2680 snr = '0'+Parser->Data.snrL2[i];
2681 }
2682 if(df & GNSSDF_L5DATA)
2683 {
2684 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL5)
2685 lli = '1';
2686 snr = ' ';
2687 }
2688 RTCM3Text("%14.3f%c%c",
2689 Parser->Data.measdata[i][pos],lli,snr);
2690 }
2691 else
2692 { /* no or illegal data */
2693 RTCM3Text(" ");
2694 }
2695 }
2696 }
2697 RTCM3Text("\n");
2698 }
2699 }
2700 else
2701 {
2702 RTCM3Text(" %02d %2d %2d %2d %2d %10.7f 0%3d",
2703 cti.year%100, cti.month, cti.day, cti.hour, cti.minute, cti.second
2704 + fmod(Parser->Data.timeofweek/1000.0,1.0), Parser->Data.numsats);
2705 for(i = 0; i < 12 && i < Parser->Data.numsats; ++i)
2706 {
2707 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2708 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2709 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2710 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2711 RTCM3Text("R%02d", Parser->Data.satellites[i]
2712 - (PRN_GLONASS_START-1));
2713 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2714 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2715 RTCM3Text("S%02d", Parser->Data.satellites[i]
2716 - PRN_SBAS_START+20);
2717 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2718 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2719 RTCM3Text("E%02d", Parser->Data.satellites[i]
2720 - (PRN_GALILEO_START-1));
2721 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2722 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2723 RTCM3Text("E%02d", Parser->Data.satellites[i]
2724 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2725 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2726 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2727 RTCM3Text("J%02d", Parser->Data.satellites[i]
2728 - (PRN_QZSS_START-1));
2729 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2730 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2731 RTCM3Text("C%02d", Parser->Data.satellites[i]
2732 - (PRN_COMPASS_START-1));
2733 else
2734 RTCM3Text("%3d", Parser->Data.satellites[i]);
2735 }
2736 RTCM3Text("\n");
2737 o = 12;
2738 j = Parser->Data.numsats - 12;
2739 while(j > 0)
2740 {
2741 RTCM3Text(" ");
2742 for(i = o; i < o+12 && i < Parser->Data.numsats; ++i)
2743 {
2744 if(Parser->Data.satellites[i] <= PRN_GPS_END)
2745 RTCM3Text("G%02d", Parser->Data.satellites[i]);
2746 else if(Parser->Data.satellites[i] >= PRN_GLONASS_START
2747 && Parser->Data.satellites[i] <= PRN_GLONASS_END)
2748 RTCM3Text("R%02d", Parser->Data.satellites[i]
2749 - (PRN_GLONASS_START-1));
2750 else if(Parser->Data.satellites[i] >= PRN_SBAS_START
2751 && Parser->Data.satellites[i] <= PRN_SBAS_END)
2752 RTCM3Text("S%02d", Parser->Data.satellites[i]
2753 - PRN_SBAS_START+20);
2754 else if(Parser->Data.satellites[i] >= PRN_GALILEO_START
2755 && Parser->Data.satellites[i] <= PRN_GALILEO_END)
2756 RTCM3Text("E%02d", Parser->Data.satellites[i]
2757 - (PRN_GALILEO_START-1));
2758 else if(Parser->Data.satellites[i] >= PRN_GIOVE_START
2759 && Parser->Data.satellites[i] <= PRN_GIOVE_END)
2760 RTCM3Text("E%02d", Parser->Data.satellites[i]
2761 - (PRN_GIOVE_START-PRN_GIOVE_OFFSET));
2762 else if(Parser->Data.satellites[i] >= PRN_QZSS_START
2763 && Parser->Data.satellites[i] <= PRN_QZSS_END)
2764 RTCM3Text("J%02d", Parser->Data.satellites[i]
2765 - (PRN_QZSS_START-1));
2766 else if(Parser->Data.satellites[i] >= PRN_COMPASS_START
2767 && Parser->Data.satellites[i] <= PRN_COMPASS_END)
2768 RTCM3Text("C%02d", Parser->Data.satellites[i]
2769 - (PRN_COMPASS_START-1));
2770 else
2771 RTCM3Text("%3d", Parser->Data.satellites[i]);
2772 }
2773 RTCM3Text("\n");
2774 j -= 12;
2775 o += 12;
2776 }
2777 for(i = 0; i < Parser->Data.numsats; ++i)
2778 {
2779 for(j = 0; j < Parser->numdatatypesGPS; ++j)
2780 {
2781 int v = 0;
2782 int df = Parser->dataflag[j];
2783 int pos = Parser->datapos[j];
2784 if((Parser->Data.dataflags[i] & df)
2785 && !isnan(Parser->Data.measdata[i][pos])
2786 && !isinf(Parser->Data.measdata[i][pos]))
2787 {
2788 v = 1;
2789 }
2790 else
2791 {
2792 df = Parser->dataflagGPS[j];
2793 pos = Parser->dataposGPS[j];
2794
2795 if((Parser->Data.dataflags[i] & df)
2796 && !isnan(Parser->Data.measdata[i][pos])
2797 && !isinf(Parser->Data.measdata[i][pos]))
2798 {
2799 v = 1;
2800 }
2801 }
2802
2803 if(!v)
2804 { /* no or illegal data */
2805 RTCM3Text(" ");
2806 }
2807 else
2808 {
2809 char lli = ' ';
2810 char snr = ' ';
2811 if(df & (GNSSDF_L1CDATA|GNSSDF_L1PDATA))
2812 {
2813 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL1)
2814 lli = '1';
2815 snr = '0'+Parser->Data.snrL1[i];
2816 }
2817 if(df & (GNSSDF_L2CDATA|GNSSDF_L2PDATA))
2818 {
2819 if(Parser->Data.dataflags2[i]
2820 & (GNSSDF2_LOCKLOSSL2|GNSSDF2_XCORRL2))
2821 {
2822 lli = '0';
2823 if(Parser->Data.dataflags2[i] & GNSSDF2_LOCKLOSSL2)
2824 lli += 1;
2825 if(Parser->Data.dataflags2[i] & GNSSDF2_XCORRL2)
2826 lli += 4;
2827 }
2828 snr = '0'+Parser->Data.snrL2[i];
2829 }
2830 if((df & GNSSDF_P2DATA) && (Parser->Data.dataflags2[i]
2831 & GNSSDF2_XCORRL2))
2832 lli = '4';
2833 RTCM3Text("%14.3f%c%c",
2834 Parser->Data.measdata[i][pos],lli,snr);
2835 }
2836 if(j%5 == 4 || j == Parser->numdatatypesGPS-1)
2837 RTCM3Text("\n");
2838 }
2839 }
2840 }
2841 }
2842 }
2843 }
2844}
2845
2846#ifndef NO_RTCM3_MAIN
2847static char datestr[] = "$Date: 2012-06-28 12:11:09 +0000 (Thu, 28 Jun 2012) $";
2848
2849/* The string, which is send as agent in HTTP request */
2850#define AGENTSTRING "NTRIP NtripRTCM3ToRINEX"
2851
2852#define MAXDATASIZE 1000 /* max number of bytes we can get at once */
2853
2854static const char encodingTable [64] = {
2855 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
2856 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
2857 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
2858 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
2859};
2860
2861/* does not buffer overrun, but breaks directly after an error */
2862/* returns the number of required bytes */
2863static int encode(char *buf, int size, const char *user, const char *pwd)
2864{
2865 unsigned char inbuf[3];
2866 char *out = buf;
2867 int i, sep = 0, fill = 0, bytes = 0;
2868
2869 while(*user || *pwd)
2870 {
2871 i = 0;
2872 while(i < 3 && *user) inbuf[i++] = *(user++);
2873 if(i < 3 && !sep) {inbuf[i++] = ':'; ++sep; }
2874 while(i < 3 && *pwd) inbuf[i++] = *(pwd++);
2875 while(i < 3) {inbuf[i++] = 0; ++fill; }
2876 if(out-buf < size-1)
2877 *(out++) = encodingTable[(inbuf [0] & 0xFC) >> 2];
2878 if(out-buf < size-1)
2879 *(out++) = encodingTable[((inbuf [0] & 0x03) << 4)
2880 | ((inbuf [1] & 0xF0) >> 4)];
2881 if(out-buf < size-1)
2882 {
2883 if(fill == 2)
2884 *(out++) = '=';
2885 else
2886 *(out++) = encodingTable[((inbuf [1] & 0x0F) << 2)
2887 | ((inbuf [2] & 0xC0) >> 6)];
2888 }
2889 if(out-buf < size-1)
2890 {
2891 if(fill >= 1)
2892 *(out++) = '=';
2893 else
2894 *(out++) = encodingTable[inbuf [2] & 0x3F];
2895 }
2896 bytes += 4;
2897 }
2898 if(out-buf < size)
2899 *out = 0;
2900 return bytes;
2901}
2902
2903static int stop = 0;
2904
2905struct Args
2906{
2907 const char *server;
2908 const char *port;
2909 int mode;
2910 int timeout;
2911 int rinex3;
2912 const char *user;
2913 const char *password;
2914 const char *proxyhost;
2915 const char *proxyport;
2916 const char *nmea;
2917 const char *data;
2918 const char *headerfile;
2919 const char *gpsephemeris;
2920 const char *glonassephemeris;
2921};
2922
2923/* option parsing */
2924#ifdef NO_LONG_OPTS
2925#define LONG_OPT(a)
2926#else
2927#define LONG_OPT(a) a
2928static struct option opts[] = {
2929{ "data", required_argument, 0, 'd'},
2930{ "server", required_argument, 0, 's'},
2931{ "password", required_argument, 0, 'p'},
2932{ "port", required_argument, 0, 'r'},
2933{ "timeout", required_argument, 0, 't'},
2934{ "header", required_argument, 0, 'f'},
2935{ "user", required_argument, 0, 'u'},
2936{ "gpsephemeris", required_argument, 0, 'E'},
2937{ "glonassephemeris", required_argument, 0, 'G'},
2938{ "rinex3", no_argument, 0, '3'},
2939{ "proxyport", required_argument, 0, 'R'},
2940{ "proxyhost", required_argument, 0, 'S'},
2941{ "nmea", required_argument, 0, 'n'},
2942{ "mode", required_argument, 0, 'M'},
2943{ "help", no_argument, 0, 'h'},
2944{0,0,0,0}};
2945#endif
2946#define ARGOPT "-d:s:p:r:t:f:u:E:G:M:S:R:n:h3"
2947
2948enum MODE { HTTP = 1, RTSP = 2, NTRIP1 = 3, AUTO = 4, END };
2949
2950static const char *geturl(const char *url, struct Args *args)
2951{
2952 static char buf[1000];
2953 static char *Buffer = buf;
2954 static char *Bufend = buf+sizeof(buf);
2955
2956 if(strncmp("ntrip:", url, 6))
2957 return "URL must start with 'ntrip:'.";
2958 url += 6; /* skip ntrip: */
2959
2960 if(*url != '@' && *url != '/')
2961 {
2962 /* scan for mountpoint */
2963 args->data = Buffer;
2964 while(*url && *url != '@' && *url != ';' &&*url != '/' && Buffer != Bufend)
2965 *(Buffer++) = *(url++);
2966 if(Buffer == args->data)
2967 return "Mountpoint required.";
2968 else if(Buffer >= Bufend-1)
2969 return "Parsing buffer too short.";
2970 *(Buffer++) = 0;
2971 }
2972
2973 if(*url == '/') /* username and password */
2974 {
2975 ++url;
2976 args->user = Buffer;
2977 while(*url && *url != '@' && *url != ';' && *url != ':' && Buffer != Bufend)
2978 *(Buffer++) = *(url++);
2979 if(Buffer == args->user)
2980 return "Username cannot be empty.";
2981 else if(Buffer >= Bufend-1)
2982 return "Parsing buffer too short.";
2983 *(Buffer++) = 0;
2984
2985 if(*url == ':') ++url;
2986
2987 args->password = Buffer;
2988 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
2989 *(Buffer++) = *(url++);
2990 if(Buffer == args->password)
2991 return "Password cannot be empty.";
2992 else if(Buffer >= Bufend-1)
2993 return "Parsing buffer too short.";
2994 *(Buffer++) = 0;
2995 }
2996
2997 if(*url == '@') /* server */
2998 {
2999 ++url;
3000 if(*url != '@' && *url != ':')
3001 {
3002 args->server = Buffer;
3003 while(*url && *url != '@' && *url != ':' && *url != ';' && Buffer != Bufend)
3004 *(Buffer++) = *(url++);
3005 if(Buffer == args->server)
3006 return "Servername cannot be empty.";
3007 else if(Buffer >= Bufend-1)
3008 return "Parsing buffer too short.";
3009 *(Buffer++) = 0;
3010 }
3011
3012 if(*url == ':')
3013 {
3014 ++url;
3015 args->port = Buffer;
3016 while(*url && *url != '@' && *url != ';' && Buffer != Bufend)
3017 *(Buffer++) = *(url++);
3018 if(Buffer == args->port)
3019 return "Port cannot be empty.";
3020 else if(Buffer >= Bufend-1)
3021 return "Parsing buffer too short.";
3022 *(Buffer++) = 0;
3023 }
3024
3025 if(*url == '@') /* proxy */
3026 {
3027 ++url;
3028 args->proxyhost = Buffer;
3029 while(*url && *url != ':' && *url != ';' && Buffer != Bufend)
3030 *(Buffer++) = *(url++);
3031 if(Buffer == args->proxyhost)
3032 return "Proxy servername cannot be empty.";
3033 else if(Buffer >= Bufend-1)
3034 return "Parsing buffer too short.";
3035 *(Buffer++) = 0;
3036
3037 if(*url == ':')
3038 {
3039 ++url;
3040 args->proxyport = Buffer;
3041 while(*url && *url != ';' && Buffer != Bufend)
3042 *(Buffer++) = *(url++);
3043 if(Buffer == args->proxyport)
3044 return "Proxy port cannot be empty.";
3045 else if(Buffer >= Bufend-1)
3046 return "Parsing buffer too short.";
3047 *(Buffer++) = 0;
3048 }
3049 }
3050 }
3051 if(*url == ';') /* NMEA */
3052 {
3053 args->nmea = ++url;
3054 while(*url)
3055 ++url;
3056 }
3057
3058 return *url ? "Garbage at end of server string." : 0;
3059}
3060
3061static int getargs(int argc, char **argv, struct Args *args)
3062{
3063 int res = 1;
3064 int getoptr;
3065 int help = 0;
3066 char *t;
3067
3068 args->server = "www.euref-ip.net";
3069 args->port = "2101";
3070 args->timeout = 60;
3071 args->user = "";
3072 args->password = "";
3073 args->data = 0;
3074 args->headerfile = 0;
3075 args->gpsephemeris = 0;
3076 args->glonassephemeris = 0;
3077 args->rinex3 = 0;
3078 args->nmea = 0;
3079 args->proxyhost = 0;
3080 args->proxyport = "2101";
3081 args->mode = AUTO;
3082 help = 0;
3083
3084 do
3085 {
3086
3087#ifdef NO_LONG_OPTS
3088 switch((getoptr = getopt(argc, argv, ARGOPT)))
3089#else
3090 switch((getoptr = getopt_long(argc, argv, ARGOPT, opts, 0)))
3091#endif
3092 {
3093 case 's': args->server = optarg; break;
3094 case 'u': args->user = optarg; break;
3095 case 'p': args->password = optarg; break;
3096 case 'd': args->data = optarg; break;
3097 case 'f': args->headerfile = optarg; break;
3098 case 'E': args->gpsephemeris = optarg; break;
3099 case 'G': args->glonassephemeris = optarg; break;
3100 case 'r': args->port = optarg; break;
3101 case '3': args->rinex3 = 1; break;
3102 case 'S': args->proxyhost = optarg; break;
3103 case 'n': args->nmea = optarg; break;
3104 case 'R': args->proxyport = optarg; break;
3105 case 'h': help=1; break;
3106 case 'M':
3107 args->mode = 0;
3108 if (!strcmp(optarg,"n") || !strcmp(optarg,"ntrip1"))
3109 args->mode = NTRIP1;
3110 else if(!strcmp(optarg,"h") || !strcmp(optarg,"http"))
3111 args->mode = HTTP;
3112 else if(!strcmp(optarg,"r") || !strcmp(optarg,"rtsp"))
3113 args->mode = RTSP;
3114 else if(!strcmp(optarg,"a") || !strcmp(optarg,"auto"))
3115 args->mode = AUTO;
3116 else args->mode = atoi(optarg);
3117 if((args->mode == 0) || (args->mode >= END))
3118 {
3119 fprintf(stderr, "Mode %s unknown\n", optarg);
3120 res = 0;
3121 }
3122 break;
3123 case 't':
3124 args->timeout = strtoul(optarg, &t, 10);
3125 if((t && *t) || args->timeout < 0)
3126 res = 0;
3127 break;
3128
3129 case 1:
3130 {
3131 const char *err;
3132 if((err = geturl(optarg, args)))
3133 {
3134 RTCM3Error("%s\n\n", err);
3135 res = 0;
3136 }
3137 }
3138 break;
3139 case -1: break;
3140 }
3141 } while(getoptr != -1 || !res);
3142
3143 datestr[0] = datestr[7];
3144 datestr[1] = datestr[8];
3145 datestr[2] = datestr[9];
3146 datestr[3] = datestr[10];
3147 datestr[5] = datestr[12];
3148 datestr[6] = datestr[13];
3149 datestr[8] = datestr[15];
3150 datestr[9] = datestr[16];
3151 datestr[4] = datestr[7] = '-';
3152 datestr[10] = 0;
3153
3154 if(args->gpsephemeris && args->glonassephemeris && args->rinex3)
3155 {
3156 RTCM3Error("RINEX3 produces a combined ephemeris file, but 2 files were specified.\n"
3157 "Please specify only one navigation file.\n");
3158 res = 0;
3159 }
3160 else if(!res || help)
3161 {
3162 RTCM3Error("Version %s (%s) GPL" COMPILEDATE
3163 "\nUsage: %s -s server -u user ...\n"
3164 " -d " LONG_OPT("--data ") "the requested data set\n"
3165 " -f " LONG_OPT("--headerfile ") "file for RINEX header information\n"
3166 " -s " LONG_OPT("--server ") "the server name or address\n"
3167 " -p " LONG_OPT("--password ") "the login password\n"
3168 " -r " LONG_OPT("--port ") "the server port number (default 2101)\n"
3169 " -t " LONG_OPT("--timeout ") "timeout in seconds (default 60)\n"
3170 " -u " LONG_OPT("--user ") "the user name\n"
3171 " -E " LONG_OPT("--gpsephemeris ") "output file for GPS ephemeris data\n"
3172 " -G " LONG_OPT("--glonassephemeris ") "output file for GLONASS ephemeris data\n"
3173 " -3 " LONG_OPT("--rinex3 ") "output RINEX type 3 data\n"
3174 " -S " LONG_OPT("--proxyhost ") "proxy name or address\n"
3175 " -R " LONG_OPT("--proxyport ") "proxy port, optional (default 2101)\n"
3176 " -n " LONG_OPT("--nmea ") "NMEA string for sending to server\n"
3177 " -M " LONG_OPT("--mode ") "mode for data request\n"
3178 " Valid modes are:\n"
3179 " 1, h, http NTRIP Version 2.0 Caster in TCP/IP mode\n"
3180 " 2, r, rtsp NTRIP Version 2.0 Caster in RTSP/RTP mode\n"
3181 " 3, n, ntrip1 NTRIP Version 1.0 Caster\n"
3182 " 4, a, auto automatic detection (default)\n"
3183 "or using an URL:\n%s ntrip:data[/user[:password]][@[server][:port][@proxyhost[:proxyport]]][;nmea]\n"
3184 , revisionstr, datestr, argv[0], argv[0]);
3185 exit(1);
3186 }
3187 return res;
3188}
3189
3190/* let the output complete a block if necessary */
3191static void signalhandler(int sig)
3192{
3193 if(!stop)
3194 {
3195 RTCM3Error("Stop signal number %d received. "
3196 "Trying to terminate gentle.\n", sig);
3197 stop = 1;
3198 alarm(1);
3199 }
3200}
3201
3202#ifndef WINDOWSVERSION
3203static void WaitMicro(int mic)
3204{
3205 struct timeval tv;
3206 tv.tv_sec = mic/1000000;
3207 tv.tv_usec = mic%1000000;
3208#ifdef DEBUG
3209 fprintf(stderr, "Waiting %d micro seconds\n", mic);
3210#endif
3211 select(0, 0, 0, 0, &tv);
3212}
3213#else /* WINDOWSVERSION */
3214void WaitMicro(int mic)
3215{
3216 Sleep(mic/1000);
3217}
3218#endif /* WINDOWSVERSION */
3219
3220#define ALARMTIME (2*60)
3221
3222/* for some reason we had to abort hard (maybe waiting for data */
3223#ifdef __GNUC__
3224static __attribute__ ((noreturn)) void signalhandler_alarm(
3225int sig __attribute__((__unused__)))
3226#else /* __GNUC__ */
3227static void signalhandler_alarm(int sig)
3228#endif /* __GNUC__ */
3229{
3230 RTCM3Error("Programm forcefully terminated.\n");
3231 exit(1);
3232}
3233
3234int main(int argc, char **argv)
3235{
3236 struct Args args;
3237 struct RTCM3ParserData Parser;
3238
3239 setbuf(stdout, 0);
3240 setbuf(stdin, 0);
3241 setbuf(stderr, 0);
3242
3243 fixrevision();
3244
3245 signal(SIGINT, signalhandler);
3246 signal(SIGALRM,signalhandler_alarm);
3247 signal(SIGQUIT,signalhandler);
3248 signal(SIGTERM,signalhandler);
3249 signal(SIGPIPE,signalhandler);
3250 memset(&Parser, 0, sizeof(Parser));
3251 {
3252 time_t tim;
3253 tim = time(0) - ((10*365+2+5)*24*60*60+LEAPSECONDS);
3254 Parser.GPSWeek = tim/(7*24*60*60);
3255 Parser.GPSTOW = tim%(7*24*60*60);
3256 }
3257
3258 if(getargs(argc, argv, &args))
3259 {
3260 int sockfd, numbytes;
3261 char buf[MAXDATASIZE];
3262 struct sockaddr_in their_addr; /* connector's address information */
3263 struct hostent *he;
3264 struct servent *se;
3265 const char *server, *port, *proxyserver = 0;
3266 char proxyport[6];
3267 char *b;
3268 long i;
3269 struct timeval tv;
3270
3271 alarm(ALARMTIME);
3272
3273 Parser.headerfile = args.headerfile;
3274 Parser.glonassephemeris = args.glonassephemeris;
3275 Parser.gpsephemeris = args.gpsephemeris;
3276 Parser.rinex3 = args.rinex3;
3277
3278 if(args.proxyhost)
3279 {
3280 int p;
3281 if((i = strtol(args.port, &b, 10)) && (!b || !*b))
3282 p = i;
3283 else if(!(se = getservbyname(args.port, 0)))
3284 {
3285 RTCM3Error("Can't resolve port %s.", args.port);
3286 exit(1);
3287 }
3288 else
3289 {
3290 p = ntohs(se->s_port);
3291 }
3292 snprintf(proxyport, sizeof(proxyport), "%d", p);
3293 port = args.proxyport;
3294 proxyserver = args.server;
3295 server = args.proxyhost;
3296 }
3297 else
3298 {
3299 server = args.server;
3300 port = args.port;
3301 }
3302
3303 memset(&their_addr, 0, sizeof(struct sockaddr_in));
3304 if((i = strtol(port, &b, 10)) && (!b || !*b))
3305 their_addr.sin_port = htons(i);
3306 else if(!(se = getservbyname(port, 0)))
3307 {
3308 RTCM3Error("Can't resolve port %s.", port);
3309 exit(1);
3310 }
3311 else
3312 {
3313 their_addr.sin_port = se->s_port;
3314 }
3315 if(!(he=gethostbyname(server)))
3316 {
3317 RTCM3Error("Server name lookup failed for '%s'.\n", server);
3318 exit(1);
3319 }
3320 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
3321 {
3322 perror("socket");
3323 exit(1);
3324 }
3325
3326 tv.tv_sec = args.timeout;
3327 tv.tv_usec = 0;
3328 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval) ) == -1)
3329 {
3330 RTCM3Error("Function setsockopt: %s\n", strerror(errno));
3331 exit(1);
3332 }
3333
3334 their_addr.sin_family = AF_INET;
3335 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3336
3337 if(args.data && args.mode == RTSP)
3338 {
3339 struct sockaddr_in local;
3340 int sockudp, localport;
3341 int cseq = 1;
3342 socklen_t len;
3343
3344 if((sockudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3345 {
3346 perror("socket");
3347 exit(1);
3348 }
3349 /* fill structure with local address information for UDP */
3350 memset(&local, 0, sizeof(local));
3351 local.sin_family = AF_INET;
3352 local.sin_port = htons(0);
3353 local.sin_addr.s_addr = htonl(INADDR_ANY);
3354 len = sizeof(local);
3355 /* bind() in order to get a random RTP client_port */
3356 if((bind(sockudp, (struct sockaddr *)&local, len)) < 0)
3357 {
3358 perror("bind");
3359 exit(1);
3360 }
3361 if((getsockname(sockudp, (struct sockaddr*)&local, &len)) != -1)
3362 {
3363 localport = ntohs(local.sin_port);
3364 }
3365 else
3366 {
3367 perror("local access failed");
3368 exit(1);
3369 }
3370 if(connect(sockfd, (struct sockaddr *)&their_addr,
3371 sizeof(struct sockaddr)) == -1)
3372 {
3373 perror("connect");
3374 exit(1);
3375 }
3376 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3377 "SETUP rtsp://%s%s%s/%s RTSP/1.0\r\n"
3378 "CSeq: %d\r\n"
3379 "Ntrip-Version: Ntrip/2.0\r\n"
3380 "Ntrip-Component: Ntripclient\r\n"
3381 "User-Agent: %s/%s\r\n"
3382 "Transport: RTP/GNSS;unicast;client_port=%u\r\n"
3383 "Authorization: Basic ",
3384 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3385 args.data, cseq++, AGENTSTRING, revisionstr, localport);
3386 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3387 {
3388 RTCM3Error("Requested data too long\n");
3389 exit(1);
3390 }
3391 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3392 if(i > MAXDATASIZE-4)
3393 {
3394 RTCM3Error("Username and/or password too long\n");
3395 exit(1);
3396 }
3397 buf[i++] = '\r';
3398 buf[i++] = '\n';
3399 buf[i++] = '\r';
3400 buf[i++] = '\n';
3401 if(args.nmea)
3402 {
3403 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3404 if(j >= 0 && j < MAXDATASIZE-i)
3405 i += j;
3406 else
3407 {
3408 RTCM3Error("NMEA string too long\n");
3409 exit(1);
3410 }
3411 }
3412 if(send(sockfd, buf, (size_t)i, 0) != i)
3413 {
3414 perror("send");
3415 exit(1);
3416 }
3417 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3418 {
3419 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3420 {
3421 int serverport = 0, session = 0;
3422 const char *portcheck = "server_port=";
3423 const char *sessioncheck = "session: ";
3424 int l = strlen(portcheck)-1;
3425 int j=0;
3426 for(i = 0; j != l && i < numbytes-l; ++i)
3427 {
3428 for(j = 0; j < l && tolower(buf[i+j]) == portcheck[j]; ++j)
3429 ;
3430 }
3431 if(i == numbytes-l)
3432 {
3433 RTCM3Error("No server port number found\n");
3434 exit(1);
3435 }
3436 else
3437 {
3438 i+=l;
3439 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3440 serverport = serverport * 10 + buf[i++]-'0';
3441 if(buf[i] != '\r' && buf[i] != ';')
3442 {
3443 RTCM3Error("Could not extract server port\n");
3444 exit(1);
3445 }
3446 }
3447 l = strlen(sessioncheck)-1;
3448 j=0;
3449 for(i = 0; j != l && i < numbytes-l; ++i)
3450 {
3451 for(j = 0; j < l && tolower(buf[i+j]) == sessioncheck[j]; ++j)
3452 ;
3453 }
3454 if(i == numbytes-l)
3455 {
3456 RTCM3Error("No session number found\n");
3457 exit(1);
3458 }
3459 else
3460 {
3461 i+=l;
3462 while(i < numbytes && buf[i] >= '0' && buf[i] <= '9')
3463 session = session * 10 + buf[i++]-'0';
3464 if(buf[i] != '\r')
3465 {
3466 RTCM3Error("Could not extract session number\n");
3467 exit(1);
3468 }
3469 }
3470
3471 i = snprintf(buf, MAXDATASIZE,
3472 "PLAY rtsp://%s%s%s/%s RTSP/1.0\r\n"
3473 "CSeq: %d\r\n"
3474 "Session: %d\r\n"
3475 "\r\n",
3476 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3477 args.data, cseq++, session);
3478
3479 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3480 {
3481 RTCM3Error("Requested data too long\n");
3482 exit(1);
3483 }
3484 if(send(sockfd, buf, (size_t)i, 0) != i)
3485 {
3486 perror("send");
3487 exit(1);
3488 }
3489 if((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3490 {
3491 if(numbytes >= 17 && !strncmp(buf, "RTSP/1.0 200 OK\r\n", 17))
3492 {
3493 struct sockaddr_in addrRTP;
3494 /* fill structure with caster address information for UDP */
3495 memset(&addrRTP, 0, sizeof(addrRTP));
3496 addrRTP.sin_family = AF_INET;
3497 addrRTP.sin_port = htons(serverport);
3498 their_addr.sin_addr = *((struct in_addr *)he->h_addr);
3499 len = sizeof(addrRTP);
3500 int ts = 0;
3501 int sn = 0;
3502 int ssrc = 0;
3503 int init = 0;
3504 int u, v, w;
3505 while(!stop && (i = recvfrom(sockudp, buf, 1526, 0,
3506 (struct sockaddr*) &addrRTP, &len)) > 0)
3507 {
3508 alarm(ALARMTIME);
3509 if(i >= 12+1 && (unsigned char)buf[0] == (2 << 6) && buf[1] == 0x60)
3510 {
3511 u= ((unsigned char)buf[2]<<8)+(unsigned char)buf[3];
3512 v = ((unsigned char)buf[4]<<24)+((unsigned char)buf[5]<<16)
3513 +((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
3514 w = ((unsigned char)buf[8]<<24)+((unsigned char)buf[9]<<16)
3515 +((unsigned char)buf[10]<<8)+(unsigned char)buf[11];
3516
3517 if(init)
3518 {
3519 int z;
3520 if(u < -30000 && sn > 30000) sn -= 0xFFFF;
3521 if(ssrc != w || ts > v)
3522 {
3523 RTCM3Error("Illegal UDP data received.\n");
3524 exit(1);
3525 }
3526 if(u > sn) /* don't show out-of-order packets */
3527 for(z = 12; z < i && !stop; ++z)
3528 HandleByte(&Parser, (unsigned int) buf[z]);
3529 }
3530 sn = u; ts = v; ssrc = w; init = 1;
3531 }
3532 else
3533 {
3534 RTCM3Error("Illegal UDP header.\n");
3535 exit(1);
3536 }
3537 }
3538 }
3539 i = snprintf(buf, MAXDATASIZE,
3540 "TEARDOWN rtsp://%s%s%s/%s RTSP/1.0\r\n"
3541 "CSeq: %d\r\n"
3542 "Session: %d\r\n"
3543 "\r\n",
3544 args.server, proxyserver ? ":" : "", proxyserver ? args.port : "",
3545 args.data, cseq++, session);
3546
3547 if(i > MAXDATASIZE || i < 0) /* second check for old glibc */
3548 {
3549 RTCM3Error("Requested data too long\n");
3550 exit(1);
3551 }
3552 if(send(sockfd, buf, (size_t)i, 0) != i)
3553 {
3554 perror("send");
3555 exit(1);
3556 }
3557 }
3558 else
3559 {
3560 RTCM3Error("Could not start data stream.\n");
3561 exit(1);
3562 }
3563 }
3564 else
3565 {
3566 RTCM3Error("Could not setup initial control connection.\n");
3567 exit(1);
3568 }
3569 }
3570 else
3571 {
3572 perror("recv");
3573 exit(1);
3574 }
3575 }
3576 else
3577 {
3578 if(connect(sockfd, (struct sockaddr *)&their_addr,
3579 sizeof(struct sockaddr)) == -1)
3580 {
3581 perror("connect");
3582 exit(1);
3583 }
3584 if(!args.data)
3585 {
3586 i = snprintf(buf, MAXDATASIZE,
3587 "GET %s%s%s%s/ HTTP/1.0\r\n"
3588 "Host: %s\r\n%s"
3589 "User-Agent: %s/%s\r\n"
3590 "Connection: close\r\n"
3591 "\r\n"
3592 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3593 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3594 args.server, args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3595 AGENTSTRING, revisionstr);
3596 }
3597 else
3598 {
3599 i=snprintf(buf, MAXDATASIZE-40, /* leave some space for login */
3600 "GET %s%s%s%s/%s HTTP/1.0\r\n"
3601 "Host: %s\r\n%s"
3602 "User-Agent: %s/%s\r\n"
3603 "Connection: close\r\n"
3604 "Authorization: Basic "
3605 , proxyserver ? "http://" : "", proxyserver ? proxyserver : "",
3606 proxyserver ? ":" : "", proxyserver ? proxyport : "",
3607 args.data, args.server,
3608 args.mode == NTRIP1 ? "" : "Ntrip-Version: Ntrip/2.0\r\n",
3609 AGENTSTRING, revisionstr);
3610 if(i > MAXDATASIZE-40 || i < 0) /* second check for old glibc */
3611 {
3612 RTCM3Error("Requested data too long\n");
3613 exit(1);
3614 }
3615 i += encode(buf+i, MAXDATASIZE-i-4, args.user, args.password);
3616 if(i > MAXDATASIZE-4)
3617 {
3618 RTCM3Error("Username and/or password too long\n");
3619 exit(1);
3620 }
3621 buf[i++] = '\r';
3622 buf[i++] = '\n';
3623 buf[i++] = '\r';
3624 buf[i++] = '\n';
3625 if(args.nmea)
3626 {
3627 int j = snprintf(buf+i, MAXDATASIZE-i, "%s\r\n", args.nmea);
3628 if(j >= 0 && j < MAXDATASIZE-i)
3629 i += j;
3630 else
3631 {
3632 RTCM3Error("NMEA string too long\n");
3633 exit(1);
3634 }
3635 }
3636 }
3637 if(send(sockfd, buf, (size_t)i, 0) != i)
3638 {
3639 perror("send");
3640 exit(1);
3641 }
3642 if(args.data)
3643 {
3644 int k = 0;
3645 int chunkymode = 0;
3646 int starttime = time(0);
3647 int lastout = starttime;
3648 int totalbytes = 0;
3649 int chunksize = 0;
3650
3651 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) != -1)
3652 {
3653 if(numbytes > 0)
3654 alarm(ALARMTIME);
3655 else
3656 {
3657 WaitMicro(100);
3658 continue;
3659 }
3660 if(!k)
3661 {
3662 if(numbytes > 17 && (!strncmp(buf, "HTTP/1.1 200 OK\r\n", 17)
3663 || !strncmp(buf, "HTTP/1.0 200 OK\r\n", 17)))
3664 {
3665 const char *datacheck = "Content-Type: gnss/data\r\n";
3666 const char *chunkycheck = "Transfer-Encoding: chunked\r\n";
3667 int l = strlen(datacheck)-1;
3668 int j=0;
3669 for(i = 0; j != l && i < numbytes-l; ++i)
3670 {
3671 for(j = 0; j < l && buf[i+j] == datacheck[j]; ++j)
3672 ;
3673 }
3674 if(i == numbytes-l)
3675 {
3676 RTCM3Error("No 'Content-Type: gnss/data' found\n");
3677 exit(1);
3678 }
3679 l = strlen(chunkycheck)-1;
3680 j=0;
3681 for(i = 0; j != l && i < numbytes-l; ++i)
3682 {
3683 for(j = 0; j < l && buf[i+j] == chunkycheck[j]; ++j)
3684 ;
3685 }
3686 if(i < numbytes-l)
3687 chunkymode = 1;
3688 }
3689 else if(numbytes < 12 || strncmp("ICY 200 OK\r\n", buf, 12))
3690 {
3691 RTCM3Error("Could not get the requested data: ");
3692 for(k = 0; k < numbytes && buf[k] != '\n' && buf[k] != '\r'; ++k)
3693 {
3694 RTCM3Error("%c", isprint(buf[k]) ? buf[k] : '.');
3695 }
3696 RTCM3Error("\n");
3697 exit(1);
3698 }
3699 else if(args.mode != NTRIP1)
3700 {
3701 if(args.mode != AUTO)
3702 {
3703 RTCM3Error("NTRIP version 2 HTTP connection failed%s.\n",
3704 args.mode == AUTO ? ", falling back to NTRIP1" : "");
3705 }
3706 if(args.mode == HTTP)
3707 exit(1);
3708 }
3709 ++k;
3710 }
3711 else
3712 {
3713 if(chunkymode)
3714 {
3715 int stop = 0;
3716 int pos = 0;
3717 while(!stop && pos < numbytes)
3718 {
3719 switch(chunkymode)
3720 {
3721 case 1: /* reading number starts */
3722 chunksize = 0;
3723 ++chunkymode; /* no break */
3724 case 2: /* during reading number */
3725 i = buf[pos++];
3726 if(i >= '0' && i <= '9') chunksize = chunksize*16+i-'0';
3727 else if(i >= 'a' && i <= 'f') chunksize = chunksize*16+i-'a'+10;
3728 else if(i >= 'A' && i <= 'F') chunksize = chunksize*16+i-'A'+10;
3729 else if(i == '\r') ++chunkymode;
3730 else if(i == ';') chunkymode = 5;
3731 else stop = 1;
3732 break;
3733 case 3: /* scanning for return */
3734 if(buf[pos++] == '\n') chunkymode = chunksize ? 4 : 1;
3735 else stop = 1;
3736 break;
3737 case 4: /* output data */
3738 i = numbytes-pos;
3739 if(i > chunksize) i = chunksize;
3740 {
3741 int z;
3742 for(z = 0; z < i && !stop; ++z)
3743 HandleByte(&Parser, (unsigned int) buf[pos+z]);
3744 }
3745 totalbytes += i;
3746 chunksize -= i;
3747 pos += i;
3748 if(!chunksize)
3749 chunkymode = 1;
3750 break;
3751 case 5:
3752 if(i == '\r') chunkymode = 3;
3753 break;
3754 }
3755 }
3756 if(stop)
3757 {
3758 RTCM3Error("Error in chunky transfer encoding\n");
3759 break;
3760 }
3761 }
3762 else
3763 {
3764 totalbytes += numbytes;
3765 {
3766 int z;
3767 for(z = 0; z < numbytes && !stop; ++z)
3768 HandleByte(&Parser, (unsigned int) buf[z]);
3769 }
3770 }
3771 if(totalbytes < 0) /* overflow */
3772 {
3773 totalbytes = 0;
3774 starttime = time(0);
3775 lastout = starttime;
3776 }
3777 }
3778 }
3779 }
3780 else
3781 {
3782 while(!stop && (numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) > 0)
3783 {
3784 alarm(ALARMTIME);
3785 fwrite(buf, (size_t)numbytes, 1, stdout);
3786 }
3787 }
3788 close(sockfd);
3789 }
3790 }
3791 return 0;
3792}
3793#endif /* NO_RTCM3_MAIN */
Note: See TracBrowser for help on using the repository browser.