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

Last change on this file since 7636 was 6868, checked in by stoecker, 10 years ago

fix galileo week

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