MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_rcv_binex.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_rcv_binex.c : BINEX receiver raw data decoder
3 *
4 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
5 * Copyright (C) 2023-2025 Cabinet Office, Japan
6 * Copyright (C) 2024-2025 Lighthouse Technology & Consulting Co. Ltd.
7 * Copyright (C) 2023-2025 Japan Aerospace Exploration Agency
8 * Copyright (C) 2023-2025 TOSHIBA ELECTRONIC TECHNOLOGIES CORPORATION
9 * Copyright (C) 2015- Mitsubishi Electric Corp.
10 * Copyright (C) 2014 Geospatial Information Authority of Japan
11 * Copyright (C) 2014 T.SUZUKI
12 * Copyright (C) 2007-2023 T.TAKASU
13 *
14 * SPDX-License-Identifier: BSD-2-Clause
15 *----------------------------------------------------------------------------*/
16#include <ctype.h>
17#include <math.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "mrtklib/mrtk_bits.h"
23#include "mrtklib/mrtk_coords.h"
24#include "mrtklib/mrtk_eph.h"
25#include "mrtklib/mrtk_mat.h"
26#include "mrtklib/mrtk_nav.h"
27#include "mrtklib/mrtk_obs.h"
28#include "mrtklib/mrtk_opt.h"
29#include "mrtklib/mrtk_rcvraw.h"
30#include "mrtklib/mrtk_rtcm.h"
31#include "mrtklib/mrtk_sys.h"
32#include "mrtklib/mrtk_time.h"
33#include "mrtklib/mrtk_trace.h"
34
35/* Local constants (duplicated from rtklib.h to avoid dependency) */
36#define PI 3.1415926535897932 /* pi */
37#define D2R (PI / 180.0) /* deg to rad */
38#define R2D (180.0 / PI) /* rad to deg */
39#define CLIGHT 299792458.0 /* speed of light (m/s) */
40#define SC2RAD 3.1415926535898 /* semi-circle to radian (IS-GPS) */
41
42#define SYS_NONE 0x00
43#define SYS_GPS 0x01
44#define SYS_SBS 0x02
45#define SYS_GLO 0x04
46#define SYS_GAL 0x08
47#define SYS_QZS 0x10
48#define SYS_CMP 0x20
49#define SYS_IRN 0x40
50
51#define TSYS_GPS 0
52#define TSYS_UTC 1
53#define TSYS_GLO 2
54#define TSYS_GAL 3
55#define TSYS_QZS 4
56#define TSYS_CMP 5
57#define TSYS_IRN 6
58
59#define FREQ1 1.57542E9 /* L1/E1/B1C frequency (Hz) */
60#define FREQ2 1.22760E9 /* L2 frequency (Hz) */
61#define FREQ5 1.17645E9 /* L5/E5a/B2a frequency (Hz) */
62#define FREQ6 1.27875E9 /* E6/L6 frequency (Hz) */
63#define FREQ7 1.20714E9 /* E5b/B2I frequency (Hz) */
64#define FREQ8 1.191795E9 /* E5ab/B2ab frequency (Hz) */
65#define FREQ9 2.492028E9 /* S frequency (Hz) */
66#define FREQ1_GLO 1.60200E9 /* GLONASS G1 base frequency (Hz) */
67#define DFRQ1_GLO 0.56250E6 /* GLONASS G1 bias frequency (Hz/n) */
68#define FREQ2_GLO 1.24600E9 /* GLONASS G2 base frequency (Hz) */
69#define DFRQ2_GLO 0.43750E6 /* GLONASS G2 bias frequency (Hz/n) */
70#define FREQ3_GLO 1.202025E9 /* GLONASS G3 frequency (Hz) */
71#define FREQ1a_GLO 1.600995E9 /* GLONASS G1a frequency (Hz) */
72#define FREQ2a_GLO 1.248060E9 /* GLONASS G2a frequency (Hz) */
73#define FREQ1_CMP 1.561098E9 /* BDS B1I frequency (Hz) */
74
75#define MINPRNGPS 1
76#define MAXPRNGPS 32
77#define MINPRNSBS 120
78#define MAXPRNSBS 158
79
80/* Power-of-2 constants */
81#define P2_5 0.03125
82#define P2_6 0.015625
83#define P2_11 4.882812500000000E-04
84#define P2_15 3.051757812500000E-05
85#define P2_17 7.629394531250000E-06
86#define P2_19 1.907348632812500E-06
87#define P2_20 9.536743164062500E-07
88#define P2_21 4.768371582031250E-07
89#define P2_23 1.192092895507810E-07
90#define P2_24 5.960464477539063E-08
91#define P2_27 7.450580596923828E-09
92#define P2_29 1.862645149230957E-09
93#define P2_30 9.313225746154785E-10
94#define P2_31 4.656612873077393E-10
95#define P2_32 2.328306436538696E-10
96#define P2_33 1.164153218269348E-10
97#define P2_34 5.820766091346740E-11
98#define P2_35 2.910383045673370E-11
99#define P2_38 3.637978807091710E-12
100#define P2_40 9.094947017729280E-13
101#define P2_43 1.136868377216160E-13
102#define P2_46 1.421085471520200E-14
103#define P2_50 8.881784197001252E-16
104#define P2_55 2.775557561562891E-17
105#define P2_59 1.734723475976810E-18
106
107/* Forward declarations for functions in rtklib (resolved at link time) */
108
109#define BNXSYNC1 0xC2 /* BINEX sync (little-endian,regular-crc) */
110#define BNXSYNC2 0xE2 /* BINEX sync (big-endian ,regular-crc) */
111#define BNXSYNC3 0xC8 /* BINEX sync (little-endian,enhanced-crc) */
112#define BNXSYNC4 0xE8 /* BINEX sync (big-endian ,enhanced-crc) */
113
114#define BNXSYNC1R 0xD2 /* BINEX sync (little-endian,regular-crc,rev) */
115#define BNXSYNC2R 0xF2 /* BINEX sync (big-endian ,regular-crc,rev) */
116#define BNXSYNC3R 0xD8 /* BINEX sync (little-endian,enhanced-crc,rev) */
117#define BNXSYNC4R 0xF8 /* BINEX sync (big-endian ,enhanced-crc,rev) */
118
119#define MIN(x, y) ((x) < (y) ? (x) : (y))
120#define SQR(x) ((x) * (x))
121
122/* URA table (URA index -> URA value) ----------------------------------------*/
123static const double ura_eph[] = {2.4, 3.4, 4.85, 6.85, 9.65, 13.65, 24.0, 48.0,
124 96.0, 192.0, 384.0, 768.0, 1536.0, 3072.0, 6144.0, 0.0};
125/* get fields (big-endian) ---------------------------------------------------*/
126#define U1(p) (*((uint8_t*)(p)))
127#define I1(p) (*((int8_t*)(p)))
128
129static uint16_t U2(uint8_t* p) {
130 uint16_t value;
131 uint8_t* q = (uint8_t*)&value + 1;
132 int i;
133 for (i = 0; i < 2; i++) {
134 *q-- = *p++;
135 }
136 return value;
137}
138static uint32_t U4(uint8_t* p) {
139 uint32_t value;
140 uint8_t* q = (uint8_t*)&value + 3;
141 int i;
142 for (i = 0; i < 4; i++) {
143 *q-- = *p++;
144 }
145 return value;
146}
147static int32_t I4(uint8_t* p) { return (int32_t)U4(p); }
148static float R4(uint8_t* p) {
149 float value;
150 uint8_t* q = (uint8_t*)&value + 3;
151 int i;
152 for (i = 0; i < 4; i++) {
153 *q-- = *p++;
154 }
155 return value;
156}
157static double R8(uint8_t* p) {
158 double value;
159 uint8_t* q = (uint8_t*)&value + 7;
160 int i;
161 for (i = 0; i < 8; i++) {
162 *q-- = *p++;
163 }
164 return value;
165}
166/* get BINEX 1-4 byte unsigned integer (big endian) --------------------------*/
167static int getbnxi(uint8_t* p, uint32_t* val) {
168 int i;
169
170 for (*val = 0, i = 0; i < 3; i++) {
171 *val = (*val << 7) + (p[i] & 0x7F);
172 if (!(p[i] & 0x80)) {
173 return i + 1;
174 }
175 }
176 *val = (*val << 8) + p[i];
177 return 4;
178}
179/* checksum 8 parity ---------------------------------------------------------*/
180static uint8_t csum8(const uint8_t* buff, int len) {
181 uint8_t cs = 0;
182 int i;
183
184 for (i = 0; i < len; i++) {
185 cs ^= buff[i];
186 }
187 return cs;
188}
189/* adjust weekly rollover of GPS time ----------------------------------------*/
190static gtime_t adjweek(gtime_t time, double tow) {
191 double tow_p;
192 int week;
193 tow_p = time2gpst(time, &week);
194 if (tow < tow_p - 302400.0) {
195 tow += 604800.0;
196 } else if (tow > tow_p + 302400.0) {
197 tow -= 604800.0;
198 }
199 return gpst2time(week, tow);
200}
201/* adjust daily rollover of time ---------------------------------------------*/
202static gtime_t adjday(gtime_t time, double tod) {
203 double ep[6], tod_p;
204 time2epoch(time, ep);
205 tod_p = ep[3] * 3600.0 + ep[4] * 60.0 + ep[5];
206 if (tod < tod_p - 43200.0) {
207 tod += 86400.0;
208 } else if (tod > tod_p + 43200.0) {
209 tod -= 86400.0;
210 }
211 ep[3] = ep[4] = ep[5] = 0.0;
212 return timeadd(epoch2time(ep), tod);
213}
214/* URA value (m) to URA index ------------------------------------------------*/
215static int uraindex(double value) {
216 int i;
217 for (i = 0; i < 15; i++) {
218 if (ura_eph[i] >= value) {
219 break;
220 }
221 }
222 return i;
223}
224/* Galileo SISA value (m) to SISA index --------------------------------------*/
225static int sisaindex(double value) {
226 if (value < 0.5) {
227 return (int)((value) / 0.01);
228 }
229 if (value < 1.0) {
230 return (int)((value - 0.5) / 0.02) + 50;
231 }
232 if (value < 2.0) {
233 return (int)((value - 1.0) / 0.04) + 75;
234 }
235 if (value <= 6.0) {
236 return (int)((value - 2.0) / 0.16) + 100;
237 }
238 return 255; /* NAPA */
239}
240/* decode BINEX mesaage 0x00: site metadata ----------------------------------*/
241static int decode_bnx_00(raw_t* raw, uint8_t* buff, int len) {
242 const static double gpst0[] = {1980, 1, 6, 0, 0, 0};
243 double x[3];
244 char *msg, str[MAXANT];
245 uint8_t* p = buff;
246 uint32_t min, qsec, src, fid = 0, flen = 0;
247 int i, ret = 0;
248
249 min = U4(p);
250 p += 4;
251 qsec = U1(p);
252 p += 1;
253 src = U1(p);
254 p += 1;
255 raw->time = timeadd(epoch2time(gpst0), min * 60.0 + qsec * 0.25);
256
257 msg = raw->msgtype + strlen(raw->msgtype);
258 if (raw->outtype) {
259 msg += sprintf(msg, " time=%s src=%d", time_str(raw->time, 0), src);
260 }
261 while (p - buff < len) {
262 p += getbnxi(p, &fid);
263 if (p - buff >= len) {
264 break;
265 }
266
267 if (fid <= 0x0c || (fid >= 0x0f && fid <= 0x1c) || (fid >= 0x20 && fid <= 0x22) || fid == 0x7f) {
268 p += getbnxi(p, &flen); /* field length*/
269 sprintf(str, "%.*s", MIN(flen, MAXANT - 1), (char*)p);
270 p += flen;
271 if (raw->outtype) {
272 msg += sprintf(msg, " [%02x]%s", fid, str);
273 }
274 if (fid == 0x08) {
275 strcpy(raw->sta.name, str);
276 } else if (fid == 0x09) {
277 strcpy(raw->sta.marker, str);
278 } else if (fid == 0x17) {
279 strcpy(raw->sta.antdes, str);
280 } else if (fid == 0x18) {
281 strcpy(raw->sta.antsno, str);
282 } else if (fid == 0x19) {
283 strcpy(raw->sta.rectype, str);
284 } else if (fid == 0x1a) {
285 strcpy(raw->sta.recsno, str);
286 } else if (fid == 0x1b) {
287 strcpy(raw->sta.recver, str);
288 }
289 ret = 5;
290 } else if (fid == 0x1d || fid == 0x1e || fid == 0x1f) {
291 if (fid == 0x1d || fid == 0x1e) {
292 p += getbnxi(p, &flen); /* subfield length */
293 p += flen;
294 }
295 for (i = 0; i < 3; i++) {
296 x[i] = R8(p);
297 p += 8;
298 }
299 if (raw->outtype) {
300 msg += sprintf(msg, " [%02x]%.3f/%.3f/%.3f", fid, x[0], x[1], x[2]);
301 }
302 if (fid == 0x1d) { /* antenna ECEF X/Y/Z position */
303 matcpy(raw->sta.pos, x, 3, 1);
304 } else if (fid == 0x1e) { /* antenna geographic position */
305 x[0] *= D2R;
306 x[1] *= D2R;
307 pos2ecef(x, raw->sta.pos);
308 } else if (fid == 0x1f) { /* antenna offset (H/E/N) */
309 raw->sta.deltype = 0; /* (E/N/U) */
310 raw->sta.del[0] = x[1];
311 raw->sta.del[1] = x[2];
312 raw->sta.del[2] = x[0];
313 }
314 ret = 5;
315 } else {
316 trace(NULL, 2, "BINEX 0x00: unsupported field fid=0x%02x\n", fid);
317 break;
318 }
319 }
320 return ret;
321}
322/* decode BINEX mesaage 0x01-00: coded (raw bytes) GNSS ephemeris ------------*/
323static int decode_bnx_01_00(raw_t* raw, uint8_t* buff, int len) {
324 trace(NULL, 2, "BINEX 0x01-00: unsupported message\n");
325 return 0;
326}
327/* decode BINEX mesaage 0x01-01: decoded GPS ephmemeris ----------------------*/
328static int decode_bnx_01_01(raw_t* raw, uint8_t* buff, int len) {
329 eph_t eph = {0};
330 uint8_t* p = buff;
331 double tow, ura, sqrtA;
332 int prn, sat, flag;
333
334 trace(NULL, 4, "BINEX 0x01-01: len=%d\n", len);
335
336 if (len >= 127) {
337 prn = U1(p) + 1;
338 p += 1;
339 eph.week = U2(p);
340 p += 2;
341 tow = I4(p);
342 p += 4;
343 eph.toes = I4(p);
344 p += 4;
345 eph.tgd[0] = R4(p);
346 p += 4;
347 eph.iodc = I4(p);
348 p += 4;
349 eph.f2 = R4(p);
350 p += 4;
351 eph.f1 = R4(p);
352 p += 4;
353 eph.f0 = R4(p);
354 p += 4;
355 eph.iode = I4(p);
356 p += 4;
357 eph.deln = R4(p) * SC2RAD;
358 p += 4;
359 eph.M0 = R8(p);
360 p += 8;
361 eph.e = R8(p);
362 p += 8;
363 sqrtA = R8(p);
364 p += 8;
365 eph.cic = R4(p);
366 p += 4;
367 eph.crc = R4(p);
368 p += 4;
369 eph.cis = R4(p);
370 p += 4;
371 eph.crs = R4(p);
372 p += 4;
373 eph.cuc = R4(p);
374 p += 4;
375 eph.cus = R4(p);
376 p += 4;
377 eph.OMG0 = R8(p);
378 p += 8;
379 eph.omg = R8(p);
380 p += 8;
381 eph.i0 = R8(p);
382 p += 8;
383 eph.OMGd = R4(p) * SC2RAD;
384 p += 4;
385 eph.idot = R4(p) * SC2RAD;
386 p += 4;
387 ura = R4(p) * 0.1;
388 p += 4;
389 eph.svh = U2(p);
390 p += 2;
391 flag = U2(p);
392 } else {
393 trace(NULL, 2, "BINEX 0x01-01: length error len=%d\n", len);
394 return -1;
395 }
396 if (!(sat = satno(SYS_GPS, prn))) {
397 trace(NULL, 2, "BINEX 0x01-01: satellite error prn=%d\n", prn);
398 return -1;
399 }
400 eph.sat = sat;
401 eph.type = 0; /* ephemeris type = LNAV */
402 eph.A = SQR(sqrtA);
403 eph.toe = gpst2time(eph.week, eph.toes);
404 eph.toc = gpst2time(eph.week, eph.toes);
405 eph.ttr = adjweek(eph.toe, tow);
406 eph.fit = flag & 0xFF;
407 eph.flag = (flag >> 8) & 0x01;
408 eph.code = (flag >> 9) & 0x03;
409 eph.sva = uraindex(ura);
410
411 if (!strstr(raw->opt, "-EPHALL")) {
412 if (raw->nav.eph[eph.sat - 1].iode == eph.iode && raw->nav.eph[eph.sat - 1].iodc == eph.iodc) {
413 return 0; /* unchanged */
414 }
415 }
416 raw->nav.eph[sat - 1] = eph;
417 raw->ephsat = sat;
418 raw->ephset = 0;
419 return 2;
420}
421/* decode BINEX mesaage 0x01-02: decoded GLONASS ephmemeris ------------------*/
422static int decode_bnx_01_02(raw_t* raw, uint8_t* buff, int len) {
423 geph_t geph = {0};
424 uint8_t* p = buff;
425 double tod, tof, tau_gps;
426 int prn, sat, day, leap;
427
428 trace(NULL, 4, "BINEX 0x01-02: len=%d\n", len);
429
430 if (len >= 119) {
431 prn = U1(p) + 1;
432 p += 1;
433 day = U2(p);
434 p += 2;
435 tod = U4(p);
436 p += 4;
437 geph.taun = -R8(p);
438 p += 8;
439 geph.gamn = R8(p);
440 p += 8;
441 tof = U4(p);
442 p += 4;
443 geph.pos[0] = R8(p) * 1E3;
444 p += 8;
445 geph.vel[0] = R8(p) * 1E3;
446 p += 8;
447 geph.acc[0] = R8(p) * 1E3;
448 p += 8;
449 geph.pos[1] = R8(p) * 1E3;
450 p += 8;
451 geph.vel[1] = R8(p) * 1E3;
452 p += 8;
453 geph.acc[1] = R8(p) * 1E3;
454 p += 8;
455 geph.pos[2] = R8(p) * 1E3;
456 p += 8;
457 geph.vel[2] = R8(p) * 1E3;
458 p += 8;
459 geph.acc[2] = R8(p) * 1E3;
460 p += 8;
461 geph.svh = U1(p) & 7;
462 p += 1; /* extended SVH (Cn_a+Cn+Bn) */
463 geph.frq = I1(p);
464 p += 1;
465 geph.age = U1(p);
466 p += 1;
467 leap = U1(p);
468 p += 1;
469 tau_gps = R8(p);
470 p += 8;
471 geph.dtaun = R8(p);
472 } else {
473 trace(NULL, 2, "BINEX 0x01-02: length error len=%d\n", len);
474 return -1;
475 }
476 if (!(sat = satno(SYS_GLO, prn))) {
477 trace(NULL, 2, "BINEX 0x01-02: satellite error prn=%d\n", prn);
478 return -1;
479 }
480 if (raw->time.time == 0) {
481 return 0;
482 }
483 geph.sat = sat;
484 geph.toe = utc2gpst(adjday(raw->time, tod - 10800.0));
485 geph.tof = utc2gpst(adjday(raw->time, tof - 10800.0));
486 geph.iode = (int)(fmod(tod, 86400.0) / 900.0 + 0.5);
487
488 if (!strstr(raw->opt, "-EPHALL")) {
489 if (fabs(timediff(geph.toe, raw->nav.geph[prn - MINPRNGLO].toe)) < 1.0 &&
490 geph.svh == raw->nav.geph[prn - MINPRNGLO].svh) {
491 return 0;
492 }
493 }
494 raw->nav.geph[prn - 1] = geph;
495 raw->ephsat = sat;
496 raw->ephset = 0;
497 return 2;
498}
499/* decode BINEX mesaage 0x01-03: decoded SBAS ephmemeris ---------------------*/
500static int decode_bnx_01_03(raw_t* raw, uint8_t* buff, int len) {
501 seph_t seph = {0};
502 uint8_t* p = buff;
503 double tow, tod, tof;
504 int prn, sat, week, iodn;
505
506 trace(NULL, 4, "BINEX 0x01-03: len=%d\n", len);
507
508 if (len >= 98) {
509 prn = U1(p);
510 p += 1;
511 week = U2(p);
512 p += 2;
513 tow = U4(p);
514 p += 4;
515 seph.af0 = R8(p);
516 p += 8;
517 tod = R4(p);
518 p += 4;
519 tof = U4(p);
520 p += 4;
521 seph.pos[0] = R8(p) * 1E3;
522 p += 8;
523 seph.vel[0] = R8(p) * 1E3;
524 p += 8;
525 seph.acc[0] = R8(p) * 1E3;
526 p += 8;
527 seph.pos[1] = R8(p) * 1E3;
528 p += 8;
529 seph.vel[1] = R8(p) * 1E3;
530 p += 8;
531 seph.acc[1] = R8(p) * 1E3;
532 p += 8;
533 seph.pos[2] = R8(p) * 1E3;
534 p += 8;
535 seph.vel[2] = R8(p) * 1E3;
536 p += 8;
537 seph.acc[2] = R8(p) * 1E3;
538 p += 8;
539 seph.svh = U1(p);
540 p += 1;
541 seph.sva = U1(p);
542 p += 1;
543 iodn = U1(p);
544 } else {
545 trace(NULL, 2, "BINEX 0x01-03 length error: len=%d\n", len);
546 return -1;
547 }
548 if (!(sat = satno(SYS_SBS, prn))) {
549 trace(NULL, 2, "BINEX 0x01-03 satellite error: prn=%d\n", prn);
550 return -1;
551 }
552 seph.sat = sat;
553 seph.t0 = gpst2time(week, tow);
554 seph.tof = adjweek(seph.t0, tof);
555
556 if (!strstr(raw->opt, "-EPHALL")) {
557 if (fabs(timediff(seph.t0, raw->nav.seph[prn - MINPRNSBS].t0)) < 1.0 &&
558 seph.sva == raw->nav.seph[prn - MINPRNSBS].sva) {
559 return 0;
560 }
561 }
562 raw->nav.seph[prn - MINPRNSBS] = seph;
563 raw->ephsat = sat;
564 raw->ephset = 0;
565 return 2;
566}
567/* decode BINEX mesaage 0x01-04: decoded Galileo ephmemeris ------------------*/
568static int decode_bnx_01_04(raw_t* raw, uint8_t* buff, int len) {
569 eph_t eph = {0};
570 uint8_t* p = buff;
571 double tow, ura, sqrtA;
572 int prn, sat, set, eph_sel = 3; /* ephemeris selection (1:I/NAV+2:F/NAV) */
573
574 trace(NULL, 4, "BINEX 0x01-04: len=%d\n", len);
575
576 if (strstr(raw->opt, "-GALFNAV")) {
577 eph_sel = 1;
578 }
579 if (strstr(raw->opt, "-GALINAV")) {
580 eph_sel = 2;
581 }
582
583 if (len >= 127) {
584 prn = U1(p) + 1;
585 p += 1;
586 eph.week = U2(p);
587 p += 2; /* gal-week = gps-week */
588 tow = I4(p);
589 p += 4;
590 eph.toes = I4(p);
591 p += 4;
592 eph.tgd[0] = R4(p);
593 p += 4; /* BGD E5a/E1 */
594 eph.tgd[1] = R4(p);
595 p += 4; /* BGD E5b/E1 */
596 eph.iode = I4(p);
597 p += 4; /* IODnav */
598 eph.f2 = R4(p);
599 p += 4;
600 eph.f1 = R4(p);
601 p += 4;
602 eph.f0 = R4(p);
603 p += 4;
604 eph.deln = R4(p) * SC2RAD;
605 p += 4;
606 eph.M0 = R8(p);
607 p += 8;
608 eph.e = R8(p);
609 p += 8;
610 sqrtA = R8(p);
611 p += 8;
612 eph.cic = R4(p);
613 p += 4;
614 eph.crc = R4(p);
615 p += 4;
616 eph.cis = R4(p);
617 p += 4;
618 eph.crs = R4(p);
619 p += 4;
620 eph.cuc = R4(p);
621 p += 4;
622 eph.cus = R4(p);
623 p += 4;
624 eph.OMG0 = R8(p);
625 p += 8;
626 eph.omg = R8(p);
627 p += 8;
628 eph.i0 = R8(p);
629 p += 8;
630 eph.OMGd = R4(p) * SC2RAD;
631 p += 4;
632 eph.idot = R4(p) * SC2RAD;
633 p += 4;
634 ura = R4(p);
635 p += 4;
636 eph.svh = U2(p);
637 p += 2;
638 eph.code = U2(p); /* data source defined as RINEX 3.03 */
639 } else {
640 trace(NULL, 2, "BINEX 0x01-04: length error len=%d\n", len);
641 return -1;
642 }
643 if (!(sat = satno(SYS_GAL, prn))) {
644 trace(NULL, 2, "BINEX 0x01-04: satellite error prn=%d\n", prn);
645 return -1;
646 }
647 set = (eph.code & (1 << 8)) ? 1 : 0; /* 0:I/NAV,1:F/NAV */
648 if (!(eph_sel & 1) && set == 0) {
649 return 0;
650 }
651 if (!(eph_sel & 2) && set == 1) {
652 return 0;
653 }
654
655 eph.sat = sat;
656 eph.type = set; /* ephemeris type = I/NAV or F/NAV */
657 eph.A = SQR(sqrtA);
658 eph.iodc = eph.iode;
659 eph.toe = gpst2time(eph.week, eph.toes);
660 eph.toc = gpst2time(eph.week, eph.toes);
661 eph.ttr = adjweek(eph.toe, tow);
662 eph.sva = ura < 0.0 ? (int)(-ura) - 1 : sisaindex(ura); /* SISA index */
663 if (!strstr(raw->opt, "-EPHALL")) {
664 if (raw->nav.eph[sat - 1 + MAXSAT * set].iode == eph.iode &&
665 fabs(timediff(raw->nav.eph[sat - 1 + MAXSAT * set].toe, eph.toe)) < 1.0 &&
666 fabs(timediff(raw->nav.eph[sat - 1 + MAXSAT * set].toc, eph.toc)) < 1.0) {
667 return 0;
668 }
669 }
670 raw->nav.eph[sat - 1 + MAXSAT * set] = eph;
671 raw->ephsat = sat;
672 raw->ephset = set;
673 return 2;
674}
675/* BDS signed 10 bit Tgd -> sec ----------------------------------------------*/
676static double bds_tgd(int tgd) {
677 tgd &= 0x3FF;
678 return (tgd & 0x200) ? -1E-10 * ((~tgd) & 0x1FF) : 1E-10 * (tgd & 0x1FF);
679}
680/* decode BINEX mesaage 0x01-05: decoded Beidou-2/Compass ephmemeris ---------*/
681static int decode_bnx_01_05(raw_t* raw, uint8_t* buff, int len) {
682 eph_t eph = {0};
683 uint8_t* p = buff;
684 double tow, toc, sqrtA;
685 int prn, sat, flag1, flag2;
686
687 trace(NULL, 4, "BINEX 0x01-05: len=%d\n", len);
688
689 if (len >= 117) {
690 prn = U1(p);
691 p += 1;
692 eph.week = U2(p);
693 p += 2;
694 tow = I4(p);
695 p += 4;
696 toc = I4(p);
697 p += 4;
698 eph.toes = I4(p);
699 p += 4;
700 eph.f2 = R4(p);
701 p += 4;
702 eph.f1 = R4(p);
703 p += 4;
704 eph.f0 = R4(p);
705 p += 4;
706 eph.deln = R4(p) * SC2RAD;
707 p += 4;
708 eph.M0 = R8(p);
709 p += 8;
710 eph.e = R8(p);
711 p += 8;
712 sqrtA = R8(p);
713 p += 8;
714 eph.cic = R4(p);
715 p += 4;
716 eph.crc = R4(p);
717 p += 4;
718 eph.cis = R4(p);
719 p += 4;
720 eph.crs = R4(p);
721 p += 4;
722 eph.cuc = R4(p);
723 p += 4;
724 eph.cus = R4(p);
725 p += 4;
726 eph.OMG0 = R8(p);
727 p += 8;
728 eph.omg = R8(p);
729 p += 8;
730 eph.i0 = R8(p);
731 p += 8;
732 eph.OMGd = R4(p) * SC2RAD;
733 p += 4;
734 eph.idot = R4(p) * SC2RAD;
735 p += 4;
736 flag1 = U2(p);
737 p += 2;
738 flag2 = U4(p);
739 } else {
740 trace(NULL, 2, "BINEX 0x01-05: length error len=%d\n", len);
741 return -1;
742 }
743 if (!(sat = satno(SYS_CMP, prn))) {
744 trace(NULL, 2, "BINEX 0x01-05: satellite error prn=%d\n", prn);
745 return 0;
746 }
747 eph.sat = sat;
748 eph.type = (prn >= 6 && prn <= 58) ? 0 : 1; /* ephemeris type = D1 or D2 */
749 eph.A = SQR(sqrtA);
750 eph.toe = gpst2time(eph.week + 1356, eph.toes + 14.0); /* bdt -> gpst */
751 eph.toc = gpst2time(eph.week + 1356, eph.toes + 14.0); /* bdt -> gpst */
752 eph.ttr = adjweek(eph.toe, tow + 14.0); /* bdt -> gpst */
753 eph.iodc = (flag1 >> 1) & 0x1F;
754 eph.iode = (flag1 >> 6) & 0x1F;
755 eph.svh = flag1 & 0x01;
756 eph.sva = flag2 & 0x0F; /* URA index */
757 eph.tgd[0] = bds_tgd(flag2 >> 4); /* TGD1 (s) */
758 eph.tgd[1] = bds_tgd(flag2 >> 14); /* TGD2 (s) */
759 eph.flag = (flag1 >> 11) & 0x07; /* nav type (0:unknown,1:IGSO/MEO,2:GEO) */
760 eph.code = (flag2 >> 25) & 0x7F;
761 /* message source (0:unknown,1:B1I,2:B1Q,3:B2I,4:B2Q,5:B3I,6:B3Q)*/
762
763 if (!strstr(raw->opt, "-EPHALL")) {
764 if (fabs(timediff(raw->nav.eph[sat - 1].toe, eph.toe)) < 1.0) {
765 return 0;
766 }
767 }
768 raw->nav.eph[sat - 1] = eph;
769 raw->ephsat = sat;
770 raw->ephset = 0;
771 return 2;
772}
773/* decode BINEX mesaage 0x01-06: decoded QZSS ephmemeris ---------------------*/
774static int decode_bnx_01_06(raw_t* raw, uint8_t* buff, int len) {
775 eph_t eph = {0};
776 uint8_t* p = buff;
777 double tow, ura, sqrtA;
778 int prn, sat, flag;
779
780 trace(NULL, 4, "BINEX 0x01-06: len=%d\n", len);
781
782 if (len >= 127) {
783 prn = U1(p);
784 p += 1;
785 eph.week = U2(p);
786 p += 2;
787 tow = I4(p);
788 p += 4;
789 eph.toes = I4(p);
790 p += 4;
791 eph.tgd[0] = R4(p);
792 p += 4;
793 eph.iodc = I4(p);
794 p += 4;
795 eph.f2 = R4(p);
796 p += 4;
797 eph.f1 = R4(p);
798 p += 4;
799 eph.f0 = R4(p);
800 p += 4;
801 eph.iode = I4(p);
802 p += 4;
803 eph.deln = R4(p) * SC2RAD;
804 p += 4;
805 eph.M0 = R8(p);
806 p += 8;
807 eph.e = R8(p);
808 p += 8;
809 sqrtA = R8(p);
810 p += 8;
811 eph.cic = R4(p);
812 p += 4;
813 eph.crc = R4(p);
814 p += 4;
815 eph.cis = R4(p);
816 p += 4;
817 eph.crs = R4(p);
818 p += 4;
819 eph.cuc = R4(p);
820 p += 4;
821 eph.cus = R4(p);
822 p += 4;
823 eph.OMG0 = R8(p);
824 p += 8;
825 eph.omg = R8(p);
826 p += 8;
827 eph.i0 = R8(p);
828 p += 8;
829 eph.OMGd = R4(p) * SC2RAD;
830 p += 4;
831 eph.idot = R4(p) * SC2RAD;
832 p += 4;
833 ura = R4(p) * 0.1;
834 p += 4;
835 eph.svh = U2(p);
836 p += 2;
837 flag = U2(p);
838 } else {
839 trace(NULL, 2, "BINEX 0x01-06: length error len=%d\n", len);
840 return -1;
841 }
842 if (!(sat = satno(SYS_QZS, prn))) {
843 trace(NULL, 2, "BINEX 0x01-06: satellite error prn=%d\n", prn);
844 return 0;
845 }
846 eph.sat = sat;
847 eph.type = 0; /* ephemeris type = LNAV */
848 eph.A = SQR(sqrtA);
849 eph.toe = gpst2time(eph.week, eph.toes);
850 eph.toc = gpst2time(eph.week, eph.toes);
851 eph.ttr = adjweek(eph.toe, tow);
852 eph.fit = (flag & 0x01) ? 0.0 : 2.0; /* 0:2hr,1:>2hr */
853 eph.sva = uraindex(ura);
854 eph.code = 2; /* codes on L2 channel */
855
856 if (!strstr(raw->opt, "-EPHALL")) {
857 if (raw->nav.eph[sat - 1].iode == eph.iode && raw->nav.eph[sat - 1].iodc == eph.iodc) {
858 return 0;
859 }
860 }
861 raw->nav.eph[sat - 1] = eph;
862 raw->ephsat = sat;
863 raw->ephset = 0;
864 return 2;
865}
866/* decode BINEX mesaage 0x01-07: decoded IRNSS ephmemeris --------------------*/
867static int decode_bnx_01_07(raw_t* raw, uint8_t* buff, int len) {
868 eph_t eph = {0};
869 uint8_t* p = buff;
870 double tow, toc, sqrtA;
871 int prn, sat, flag, iodec;
872
873 trace(NULL, 4, "BINEX 0x01-07: len=%d\n", len);
874
875 if (len >= 114) {
876 prn = U1(p);
877 p += 1;
878 eph.week = U2(p) + 1024;
879 p += 2; /* IRNSS week -> GPS week */
880 tow = I4(p);
881 p += 4;
882 toc = I4(p);
883 p += 4;
884 eph.toes = I4(p);
885 p += 4;
886 eph.f2 = R4(p);
887 p += 4;
888 eph.f1 = R4(p);
889 p += 4;
890 eph.f0 = R4(p);
891 p += 4;
892 eph.deln = R4(p) * SC2RAD;
893 p += 4;
894 eph.M0 = R8(p);
895 p += 8;
896 eph.e = R8(p);
897 p += 8;
898 sqrtA = R8(p);
899 p += 8;
900 eph.cic = R4(p);
901 p += 4;
902 eph.crc = R4(p);
903 p += 4;
904 eph.cis = R4(p);
905 p += 4;
906 eph.crs = R4(p);
907 p += 4;
908 eph.cuc = R4(p);
909 p += 4;
910 eph.cus = R4(p);
911 p += 4;
912 eph.OMG0 = R8(p);
913 p += 8;
914 eph.omg = R8(p);
915 p += 8;
916 eph.i0 = R8(p);
917 p += 8;
918 eph.OMGd = R4(p) * SC2RAD;
919 p += 4;
920 eph.idot = R4(p) * SC2RAD;
921 p += 4;
922 flag = U1(p);
923 p += 1;
924 iodec = U2(p);
925 } else {
926 trace(NULL, 2, "BINEX 0x01-07: length error len=%d\n", len);
927 return -1;
928 }
929 if (!(sat = satno(SYS_IRN, prn))) {
930 trace(NULL, 2, "BINEX 0x01-07: satellite error prn=%d\n", prn);
931 return 0;
932 }
933 eph.sat = sat;
934 eph.type = 0; /* ephemeris type = LNAV */
935 eph.A = SQR(sqrtA);
936 eph.toe = gpst2time(eph.week, eph.toes);
937 eph.toc = adjweek(eph.toe, toc);
938 eph.ttr = adjweek(eph.toe, tow);
939 eph.sva = flag & 0x0F; /* URA index (0-15) */
940 eph.svh = ((flag & 0x10) ? 2 : 0) + ((flag & 0x20) ? 1 : 0);
941 eph.iode = eph.iodc = iodec & 0xFF;
942 eph.tgd[0] = (int8_t)(iodec >> 8) * P2_31;
943
944 if (!strstr(raw->opt, "-EPHALL")) {
945 if (raw->nav.eph[sat - 1].iode == eph.iode && fabs(timediff(raw->nav.eph[sat - 1].toe, eph.toe)) < 1.0 &&
946 fabs(timediff(raw->nav.eph[sat - 1].toc, eph.toc)) < 1.0) {
947 return 0;
948 }
949 }
950 raw->nav.eph[sat - 1] = eph;
951 raw->ephsat = sat;
952 raw->ephset = 0;
953 return 2;
954}
955/* decode BINEX mesaage 0x01-14: upgraded decoded Galileo ephmemeris ---------*/
956static int decode_bnx_01_14(raw_t* raw, uint8_t* buff, int len) {
957 eph_t eph = {0};
958 uint8_t* p = buff;
959 double tow, ura, sqrtA;
960 int prn, sat, tocs, set, eph_sel = 3;
961
962 trace(NULL, 4, "BINEX 0x01-14: len=%d\n", len);
963
964 if (strstr(raw->opt, "-GALFNAV")) {
965 eph_sel = 1;
966 }
967 if (strstr(raw->opt, "-GALINAV")) {
968 eph_sel = 2;
969 }
970
971 if (len >= 135) {
972 prn = U1(p) + 1;
973 p += 1;
974 eph.week = U2(p);
975 p += 2; /* gal-week = gps-week */
976 tow = I4(p);
977 p += 4;
978 tocs = I4(p);
979 p += 4;
980 eph.toes = I4(p);
981 p += 4;
982 eph.tgd[0] = R4(p);
983 p += 4; /* BGD E5a/E1 */
984 eph.tgd[1] = R4(p);
985 p += 4; /* BGD E5b/E1 */
986 eph.iode = I4(p);
987 p += 4; /* IODnav */
988 eph.f2 = R4(p);
989 p += 4;
990 eph.f1 = R4(p);
991 p += 4;
992 eph.f0 = R8(p);
993 p += 8;
994 eph.deln = R4(p) * SC2RAD;
995 p += 4;
996 eph.M0 = R8(p);
997 p += 8;
998 eph.e = R8(p);
999 p += 8;
1000 sqrtA = R8(p);
1001 p += 8;
1002 eph.cic = R4(p);
1003 p += 4;
1004 eph.crc = R4(p);
1005 p += 4;
1006 eph.cis = R4(p);
1007 p += 4;
1008 eph.crs = R4(p);
1009 p += 4;
1010 eph.cuc = R4(p);
1011 p += 4;
1012 eph.cus = R4(p);
1013 p += 4;
1014 eph.OMG0 = R8(p);
1015 p += 8;
1016 eph.omg = R8(p);
1017 p += 8;
1018 eph.i0 = R8(p);
1019 p += 8;
1020 eph.OMGd = R4(p) * SC2RAD;
1021 p += 4;
1022 eph.idot = R4(p) * SC2RAD;
1023 p += 4;
1024 ura = R4(p);
1025 p += 4;
1026 eph.svh = U2(p);
1027 p += 2;
1028 eph.code = U2(p); /* data source defined as RINEX 3.03 */
1029 } else {
1030 trace(NULL, 2, "BINEX 0x01-14: length error len=%d\n", len);
1031 return -1;
1032 }
1033 if (!(sat = satno(SYS_GAL, prn))) {
1034 trace(NULL, 2, "BINEX 0x01-14: satellite error prn=%d\n", prn);
1035 return -1;
1036 }
1037 set = (eph.code & (1 << 8)) ? 1 : 0; /* 0:I/NAV,1:F/NAV */
1038 if (!(eph_sel & 1) && set == 0) {
1039 return 0;
1040 }
1041 if (!(eph_sel & 2) && set == 1) {
1042 return 0;
1043 }
1044
1045 eph.sat = sat;
1046 eph.type = set; /* ephemeris type = I/NAV or F/NAV */
1047 eph.A = SQR(sqrtA);
1048 eph.iodc = eph.iode;
1049 eph.toe = gpst2time(eph.week, eph.toes);
1050 eph.toc = gpst2time(eph.week, tocs);
1051 eph.ttr = adjweek(eph.toe, tow);
1052 eph.sva = ura < 0.0 ? (int)(-ura) - 1 : sisaindex(ura); /* SISA index */
1053 if (!strstr(raw->opt, "-EPHALL")) {
1054 if (raw->nav.eph[sat - 1 + MAXSAT * set].iode == eph.iode &&
1055 fabs(timediff(raw->nav.eph[sat - 1 + MAXSAT * set].toe, eph.toe)) < 1.0 &&
1056 fabs(timediff(raw->nav.eph[sat - 1 + MAXSAT * set].toc, eph.toc)) < 1.0) {
1057 return 0;
1058 }
1059 }
1060 raw->nav.eph[sat - 1 + MAXSAT * set] = eph;
1061 raw->ephsat = sat;
1062 raw->ephset = set;
1063 return 2;
1064}
1065/* decode BINEX mesaage 0x01: GNSS navigation information --------------------*/
1066static int decode_bnx_01(raw_t* raw, uint8_t* buff, int len) {
1067 int srec = U1(buff), prn = U1(buff + 1);
1068
1069 if (raw->outtype) {
1070 prn = srec == 0x01 || srec == 0x02 || srec == 0x04 ? prn + 1 : (srec == 0x00 ? 0 : prn);
1071 sprintf(raw->msgtype + strlen(raw->msgtype), " subrec=%02X prn=%d", srec, prn);
1072 }
1073 switch (srec) {
1074 case 0x00:
1075 return decode_bnx_01_00(raw, buff + 1, len - 1);
1076 case 0x01:
1077 return decode_bnx_01_01(raw, buff + 1, len - 1);
1078 case 0x02:
1079 return decode_bnx_01_02(raw, buff + 1, len - 1);
1080 case 0x03:
1081 return decode_bnx_01_03(raw, buff + 1, len - 1);
1082 case 0x04:
1083 return decode_bnx_01_04(raw, buff + 1, len - 1);
1084 case 0x05:
1085 return decode_bnx_01_05(raw, buff + 1, len - 1);
1086 case 0x06:
1087 return decode_bnx_01_06(raw, buff + 1, len - 1);
1088 case 0x07:
1089 return decode_bnx_01_07(raw, buff + 1, len - 1);
1090 case 0x14:
1091 return decode_bnx_01_14(raw, buff + 1, len - 1);
1092 }
1093 return 0;
1094}
1095/* decode BINEX mesaage 0x02: generalized GNSS data --------------------------*/
1096static int decode_bnx_02(raw_t* raw, uint8_t* buff, int len) {
1097 trace(NULL, 2, "BINEX 0x02: unsupported message\n");
1098 return 0;
1099}
1100/* decode BINEX mesaage 0x03: generalized ancillary site data ----------------*/
1101static int decode_bnx_03(raw_t* raw, uint8_t* buff, int len) {
1102 trace(NULL, 2, "BINEX 0x03: unsupported message\n");
1103 return 0;
1104}
1105/* decode BINEX mesaage 0x7d: receiver internal state prototyping ------------*/
1106static int decode_bnx_7d(raw_t* raw, uint8_t* buff, int len) {
1107 trace(NULL, 2, "BINEX 0x7d: unsupported message\n");
1108 return 0;
1109}
1110/* decode BINEX mesaage 0x7e: ancillary site data prototyping ----------------*/
1111static int decode_bnx_7e(raw_t* raw, uint8_t* buff, int len) {
1112 trace(NULL, 2, "BINEX 0x7e: unsupported message\n");
1113 return 0;
1114}
1115/* decode BINEX mesaage 0x7f-00: JPL fiducial site ---------------------------*/
1116static int decode_bnx_7f_00(raw_t* raw, uint8_t* buff, int len) {
1117 trace(NULL, 2, "BINEX 0x7f-00: unsupported message\n");
1118 return 0;
1119}
1120/* decode BINEX mesaage 0x7f-01: UCAR COSMIC ---------------------------------*/
1121static int decode_bnx_7f_01(raw_t* raw, uint8_t* buff, int len) {
1122 trace(NULL, 2, "BINEX 0x7f-01: unsupported message\n");
1123 return 0;
1124}
1125/* decode BINEX mesaage 0x7f-02: Trimble 4700 --------------------------------*/
1126static int decode_bnx_7f_02(raw_t* raw, uint8_t* buff, int len) {
1127 trace(NULL, 2, "BINEX 0x7f-02: unsupported message\n");
1128 return 0;
1129}
1130/* decode BINEX mesaage 0x7f-03: Trimble NetRS -------------------------------*/
1131static int decode_bnx_7f_03(raw_t* raw, uint8_t* buff, int len) {
1132 trace(NULL, 2, "BINEX 0x7f-03: unsupported message\n");
1133 return 0;
1134}
1135/* decode BINEX mesaage 0x7f-04: Trimble NetRS -------------------------------*/
1136static int decode_bnx_7f_04(raw_t* raw, uint8_t* buff, int len) {
1137 trace(NULL, 2, "BINEX 0x7f-04: unsupported message\n");
1138 return 0;
1139}
1140/* decode BINEX mesaage 0x7f-05: Trimble NetR8 obs data ----------------------*/
1141static uint8_t* decode_bnx_7f_05_obs(raw_t* raw, uint8_t* buff, int sat, int nobs, obsd_t* data) {
1142 const uint8_t codes_gps[32] = {
1148 CODE_NONE, CODE_NONE /* 30-31 */
1149 };
1150 const uint8_t codes_glo[32] = {
1156 CODE_NONE, CODE_NONE /* 30-31 */
1157 };
1158 const uint8_t codes_gal[32] = {
1164 CODE_NONE, CODE_NONE /* 30-31 */
1165 };
1166 const uint8_t codes_sbs[32] = {
1168 CODE_L5X, CODE_L5I, CODE_L5Q, CODE_L5X /* 6- 9 */
1169 };
1170 const uint8_t codes_cmp[32] = {
1176 CODE_L6P, CODE_L6Z /* 30-31 */
1177 };
1178 const uint8_t codes_qzs[32] = {
1184 CODE_L1Z, CODE_L1B /* 30-31 */
1185 };
1186 const uint8_t codes_irn[32] = {
1188 CODE_L9A, CODE_L9B, CODE_L9C, CODE_L9X /* 6- 9 */
1189 };
1190 const uint8_t* codes = NULL;
1191 double range[8], phase[8], cnr[8], dopp[8] = {0}, acc, freq;
1192 uint8_t* p = buff;
1193 uint8_t flag, flags[4];
1194 int i, j, k, sys, prn, fcn = -10, code[8], slip[8], pri[8], idx[8];
1195 int slipcnt[8] = {0}, mask[8] = {0};
1196
1197 trace(NULL, 5, "decode_bnx_7f_05_obs: sat=%2d nobs=%2d\n", sat, nobs);
1198
1199 sys = satsys(sat, &prn);
1200
1201 switch (sys) {
1202 case SYS_GPS:
1203 codes = codes_gps;
1204 break;
1205 case SYS_GLO:
1206 codes = codes_glo;
1207 break;
1208 case SYS_GAL:
1209 codes = codes_gal;
1210 break;
1211 case SYS_QZS:
1212 codes = codes_qzs;
1213 break;
1214 case SYS_SBS:
1215 codes = codes_sbs;
1216 break;
1217 case SYS_CMP:
1218 codes = codes_cmp;
1219 break;
1220 case SYS_IRN:
1221 codes = codes_irn;
1222 break;
1223 default:
1224 codes = NULL;
1225 break; /* skip unsupported sat data */
1226 }
1227 for (i = 0; i < nobs; i++) {
1228 flag = getbitu(p, 0, 1);
1229 slip[i] = getbitu(p, 2, 1);
1230 code[i] = getbitu(p, 3, 5);
1231 p++;
1232
1233 for (j = 0; j < 4; j++) {
1234 flags[j] = 0;
1235 }
1236
1237 for (j = 0; flag && j < 4; j++) {
1238 flag = U1(p++);
1239 flags[flag & 0x03] = flag & 0x7F;
1240 flag &= 0x80;
1241 }
1242 if (flags[2]) {
1243 fcn = getbits(flags + 2, 2, 4);
1244 if (sys == SYS_GLO && !raw->nav.glo_fcn[prn - 1]) {
1245 raw->nav.glo_fcn[prn - 1] = fcn + 8; /* fcn+8 */
1246 }
1247 }
1248 acc = (flags[0] & 0x20) ? 0.0001 : 0.00002; /* phase accuracy */
1249
1250 cnr[i] = U1(p++) * 0.4;
1251
1252 if (i == 0) {
1253 cnr[i] += getbits(p, 0, 2) * 0.1;
1254 range[i] = getbitu(p, 2, 32) * 0.064 + getbitu(p, 34, 6) * 0.001;
1255 p += 5;
1256 } else if (flags[0] & 0x40) {
1257 cnr[i] += getbits(p, 0, 2) * 0.1;
1258 range[i] = range[0] + getbits(p, 4, 20) * 0.001;
1259 p += 3;
1260 } else {
1261 range[i] = range[0] + getbits(p, 0, 16) * 0.001;
1262 p += 2;
1263 }
1264 if (flags[0] & 0x40) {
1265 phase[i] = range[i] + getbits(p, 0, 24) * acc;
1266 p += 3;
1267 } else {
1268 cnr[i] += getbits(p, 0, 2) * 0.1;
1269 phase[i] = range[i] + getbits(p, 2, 22) * acc;
1270 p += 3;
1271 }
1272 if (flags[0] & 0x04) {
1273 dopp[i] = getbits(p, 0, 24) / 256.0;
1274 p += 3;
1275 }
1276 if (flags[0] & 0x08) {
1277 if (flags[0] & 0x10) {
1278 slipcnt[i] = U2(p);
1279 p += 2;
1280 } else {
1281 slipcnt[i] = U1(p);
1282 p += 1;
1283 }
1284 }
1285 trace(NULL, 5, "(%d) CODE=%2d S=%d F=%02X %02X %02X %02X\n", i + 1, code[i], slip[i], flags[0], flags[1],
1286 flags[2], flags[3]);
1287 trace(NULL, 5, "(%d) P=%13.3f L=%13.3f D=%7.1f SNR=%4.1f SCNT=%2d\n", i + 1, range[i], phase[i], dopp[i],
1288 cnr[i], slipcnt[i]);
1289 }
1290 if (!codes) {
1291 data->sat = 0;
1292 return p;
1293 }
1294 data->time = raw->time;
1295 data->sat = sat;
1296
1297 /* get code priority */
1298 for (i = 0; i < nobs; i++) {
1299 idx[i] = code2freq_idx(sys, codes[code[i]]);
1300 pri[i] = getcodepri(sys, codes[code[i]], raw->opt);
1301 }
1302 for (i = 0; i < NFREQ; i++) {
1303 for (j = 0, k = -1; j < nobs; j++) {
1304 if (idx[j] == i && (k < 0 || pri[j] > pri[k])) {
1305 k = j;
1306 }
1307 }
1308 if (k < 0) {
1309 data->P[i] = data->L[i] = 0.0;
1310 data->D[i] = 0.0f;
1311 data->SNR[i] = data->LLI[i] = 0;
1312 data->code[i] = CODE_NONE;
1313 } else {
1314 freq = code2freq(sys, codes[code[k]], fcn);
1315 data->P[i] = range[k];
1316 data->L[i] = phase[k] * freq / CLIGHT;
1317 data->D[i] = dopp[k];
1318 data->SNR[i] = (uint16_t)(cnr[k] / SNR_UNIT + 0.5);
1319 data->code[i] = codes[code[k]];
1320 data->LLI[i] = slip[k] ? 1 : 0;
1321 mask[k] = 1;
1322 }
1323 }
1324 for (; i < NFREQ + NEXOBS; i++) {
1325 for (k = 0; k < nobs; k++) {
1326 if (!mask[k]) {
1327 break;
1328 }
1329 }
1330 if (k >= nobs) {
1331 data->P[i] = data->L[i] = 0.0;
1332 data->D[i] = 0.0f;
1333 data->SNR[i] = data->LLI[i] = 0;
1334 data->code[i] = CODE_NONE;
1335 } else {
1336 freq = code2freq(sys, codes[code[k]], fcn);
1337 data->P[i] = range[k];
1338 data->L[i] = phase[k] * freq / CLIGHT;
1339 data->D[i] = dopp[k];
1340 data->SNR[i] = (uint16_t)(cnr[k] / SNR_UNIT + 0.5);
1341 data->code[i] = codes[code[k]];
1342 data->LLI[i] = slip[k] ? 1 : 0;
1343 mask[k] = 1;
1344 }
1345 }
1346 return p;
1347}
1348/* decode BINEX mesaage 0x7f-05: Trimble NetR8 -------------------------------*/
1349static int decode_bnx_7f_05(raw_t* raw, uint8_t* buff, int len) {
1350 obsd_t data = {{0}};
1351 double clkoff = 0.0, toff[16] = {0};
1352 char* msg;
1353 uint8_t* p = buff;
1354 uint32_t flag;
1355 int i, nsat, nobs, prn, sys, sat, clkrst = 0, rsys = 0, nsys = 0, tsys[16] = {0};
1356
1357 trace(NULL, 4, "decode_bnx_7f_05\n");
1358
1359 raw->obs.n = 0;
1360 flag = U1(p++);
1361 nsat = (int)(flag & 0x3F) + 1;
1362
1363 if (flag & 0x80) { /* rxclkoff */
1364 clkrst = getbitu(p, 0, 2);
1365 clkoff = getbits(p, 2, 22) * 1E-9;
1366 p += 3;
1367 }
1368 if (flag & 0x40) { /* systime */
1369 nsys = getbitu(p, 0, 4);
1370 rsys = getbitu(p, 4, 4);
1371 p++;
1372 for (i = 0; i < nsys; i++) {
1373 toff[i] = getbits(p, 0, 24) * 1E-9;
1374 tsys[i] = getbitu(p, 28, 4);
1375 p += 4;
1376 }
1377 }
1378 for (i = 0; i < nsat; i++) {
1379 prn = U1(p++);
1380 nobs = getbitu(p, 1, 3);
1381 sys = getbitu(p, 4, 4);
1382 p++;
1383
1384 trace(NULL, 5, "BINEX 0x7F-05 PRN=%3d SYS=%d NOBS=%d\n", prn, sys, nobs);
1385
1386 switch (sys) {
1387 case 0:
1388 sat = satno(SYS_GPS, prn);
1389 break;
1390 case 1:
1391 sat = satno(SYS_GLO, prn);
1392 break;
1393 case 2:
1394 sat = satno(SYS_SBS, prn);
1395 break;
1396 case 3:
1397 sat = satno(SYS_GAL, prn);
1398 break;
1399 case 4:
1400 sat = satno(SYS_CMP, prn);
1401 break;
1402 case 5:
1403 sat = satno(SYS_QZS, prn);
1404 break;
1405 case 6:
1406 sat = satno(SYS_IRN, prn);
1407 break;
1408 default:
1409 sat = 0;
1410 break;
1411 }
1412 /* decode BINEX mesaage 0x7F-05 obs data */
1413 if (!(p = decode_bnx_7f_05_obs(raw, p, sat, nobs, &data))) {
1414 return -1;
1415 }
1416
1417 if ((int)(p - buff) > len) {
1418 trace(NULL, 2, "BINEX 0x7F-05 length error: nsat=%2d len=%d\n", nsat, len);
1419 return -1;
1420 }
1421 /* save obs data to obs buffer */
1422 if (data.sat && raw->obs.n < MAXOBS) {
1423 raw->obs.data[raw->obs.n++] = data;
1424 }
1425 }
1426 if (raw->outtype) {
1427 msg = raw->msgtype + strlen(raw->msgtype);
1428 sprintf(msg, " nsat=%2d", nsat);
1429 }
1430 return raw->obs.n > 0 ? 1 : 0;
1431}
1432/* decode BINEX mesaage 0x7f: GNSS data prototyping --------------------------*/
1433static int decode_bnx_7f(raw_t* raw, uint8_t* buff, int len) {
1434 const static double gpst0[] = {1980, 1, 6, 0, 0, 0};
1435 char* msg;
1436 uint8_t* p = buff;
1437 uint32_t srec, min, msec;
1438
1439 srec = U1(p);
1440 p += 1; /* subrecord ID */
1441 min = U4(p);
1442 p += 4;
1443 msec = U2(p);
1444 p += 2;
1445 raw->time = timeadd(epoch2time(gpst0), min * 60.0);
1446 raw->time = timeadd(raw->time, msec * 0.001);
1447
1448 if (raw->outtype) {
1449 msg = raw->msgtype + strlen(raw->msgtype);
1450 sprintf(msg, " subrec=%02X time%s", srec, time_str(raw->time, 3));
1451 }
1452 switch (srec) {
1453 case 0x00:
1454 return decode_bnx_7f_00(raw, buff + 7, len - 7);
1455 case 0x01:
1456 return decode_bnx_7f_01(raw, buff + 7, len - 7);
1457 case 0x02:
1458 return decode_bnx_7f_02(raw, buff + 7, len - 7);
1459 case 0x03:
1460 return decode_bnx_7f_03(raw, buff + 7, len - 7);
1461 case 0x04:
1462 return decode_bnx_7f_04(raw, buff + 7, len - 7);
1463 case 0x05:
1464 return decode_bnx_7f_05(raw, buff + 7, len - 7);
1465 }
1466 return 0;
1467}
1468/* decode BINEX mesaage ------------------------------------------------------*/
1469static int decode_bnx(raw_t* raw) {
1470 uint32_t len, cs1, cs2;
1471 int rec, len_h;
1472
1473 rec = raw->buff[1]; /* record ID */
1474
1475 /* record and header length */
1476 len_h = getbnxi(raw->buff + 2, &len);
1477
1478 trace(NULL, 5, "decode_bnx: rec=%02x len=%d\n", rec, len);
1479
1480 /* check parity */
1481 if (raw->len - 1 < 128) {
1482 cs1 = U1(raw->buff + raw->len);
1483 cs2 = csum8(raw->buff + 1, raw->len - 1);
1484 } else {
1485 cs1 = U2(raw->buff + raw->len);
1486 cs2 = rtk_crc16(raw->buff + 1, raw->len - 1);
1487 }
1488 if (cs1 != cs2) {
1489 trace(NULL, 2, "BINEX 0x%02X parity error CS=%X %X\n", rec, cs1, cs2);
1490 return -1;
1491 }
1492 if (raw->outtype) {
1493 sprintf(raw->msgtype, "BINEX 0x%02X (%4d)", rec, raw->len);
1494 }
1495 /* decode BINEX message record */
1496 switch (rec) {
1497 case 0x00:
1498 return decode_bnx_00(raw, raw->buff + 2 + len_h, len);
1499 case 0x01:
1500 return decode_bnx_01(raw, raw->buff + 2 + len_h, len);
1501 case 0x02:
1502 return decode_bnx_02(raw, raw->buff + 2 + len_h, len);
1503 case 0x03:
1504 return decode_bnx_03(raw, raw->buff + 2 + len_h, len);
1505 case 0x7d:
1506 return decode_bnx_7d(raw, raw->buff + 2 + len_h, len);
1507 case 0x7e:
1508 return decode_bnx_7e(raw, raw->buff + 2 + len_h, len);
1509 case 0x7f:
1510 return decode_bnx_7f(raw, raw->buff + 2 + len_h, len);
1511 }
1512 return 0;
1513}
1514/* synchronize BINEX message -------------------------------------------------*/
1515static int sync_bnx(uint8_t* buff, uint8_t data) {
1516 buff[0] = buff[1];
1517 buff[1] = data;
1518
1519 return buff[0] == BNXSYNC2 && (buff[1] == 0x00 || buff[1] == 0x01 || buff[1] == 0x02 || buff[1] == 0x03 ||
1520 buff[1] == 0x7D || buff[1] == 0x7E || buff[1] == 0x7F);
1521}
1522/* input BINEX message from stream ---------------------------------------------
1523 * fetch next BINEX data and input a message from stream
1524 * args : raw_t *raw IO receiver raw data control struct
1525 * uint8_t data I stream data (1 byte)
1526 * return : status (-1: error message, 0: no message, 1: input observation data,
1527 * 2: input ephemeris, 5: input station pos/ant parameters)
1528 * notes : support only the following message (ref [1])
1529 *
1530 * - big-endian, regular CRC, forward record (sync=0xE2)
1531 * - record-subrecord:
1532 * 0x00 : site metadata (monument,marker,ref point,setup)
1533 * 0x01-01: decoded GPS ephemeris
1534 * 0x01-02: decoded GLONASS ephemeris
1535 * 0x01-03: decoded SBAS ephemeris
1536 * 0x01-04: decoded Galileo ephemeris
1537 * 0x01-05: decoded BDS-2/compass ephemeris
1538 * 0x01-06: decoded QZSS ephemeris
1539 * 0x01-07: decoded IRNSS ephemeris
1540 * 0x01-14: decoded upgraded Galileo ephemeris
1541 * 0x7f-05: GNSS data prototyping - Trimble NetR8
1542 *
1543 * to specify input options, set rtcm->opt to the following option
1544 * strings separated by spaces.
1545 *
1546 * -EPHALL : input all ephemerides
1547 * -GLss : select signal ss for GPS (ss=1C,1P,...)
1548 * -RLss : select signal ss for GLO (ss=1C,1P,...)
1549 * -ELss : select signal ss for GAL (ss=1C,1B,...)
1550 * -JLss : select signal ss for QZS (ss=1C,2C,...)
1551 * -CLss : select signal ss for BDS (ss=2I,2X,...)
1552 * -GALINAV : select I/NAV for Galileo ephemeris (default: all)
1553 * -GALFNAV : select F/NAV for Galileo ephemeris (default: all)
1554 *-----------------------------------------------------------------------------*/
1555extern int input_bnx(raw_t* raw, uint8_t data) {
1556 uint32_t len;
1557 int len_h, len_c;
1558
1559 trace(NULL, 5, "input_bnx: data=%02x\n", data);
1560
1561 /* synchronize BINEX message */
1562 if (raw->nbyte == 0) {
1563 if (!sync_bnx(raw->buff, data)) {
1564 return 0;
1565 }
1566 raw->nbyte = 2;
1567 return 0;
1568 }
1569 raw->buff[raw->nbyte++] = data;
1570 if (raw->nbyte < 4) {
1571 return 0;
1572 }
1573
1574 len_h = getbnxi(raw->buff + 2, &len);
1575
1576 raw->len = len + len_h + 2; /* length without CRC */
1577
1578 if (raw->len - 1 > 4096) {
1579 trace(NULL, 2, "BINEX length error: len=%d\n", raw->len - 1);
1580 raw->nbyte = 0;
1581 return -1;
1582 }
1583 len_c = (raw->len - 1 < 128) ? 1 : 2;
1584
1585 if (raw->nbyte < (int)(raw->len + len_c)) {
1586 return 0;
1587 }
1588 raw->nbyte = 0;
1589
1590 /* decode BINEX message */
1591 return decode_bnx(raw);
1592}
1593/* input BINEX message from file -----------------------------------------------
1594 * fetch next BINEX data and input a message from file
1595 * args : raw_t *raw IO receiver raw data control struct
1596 * FILE *fp I file pointer
1597 * return : status(-2: end of file, -1...9: same as above)
1598 *-----------------------------------------------------------------------------*/
1599extern int input_bnxf(raw_t* raw, FILE* fp) {
1600 uint32_t len;
1601 int i, data, len_h, len_c;
1602
1603 trace(NULL, 4, "input_bnxf\n");
1604
1605 if (raw->nbyte == 0) {
1606 for (i = 0;; i++) {
1607 if ((data = fgetc(fp)) == EOF) {
1608 return -2;
1609 }
1610 if (sync_bnx(raw->buff, (uint8_t)data)) {
1611 break;
1612 }
1613 if (i >= 4096) {
1614 return 0;
1615 }
1616 }
1617 }
1618 if (fread(raw->buff + 2, 1, 4, fp) < 4) {
1619 return -2;
1620 }
1621
1622 len_h = getbnxi(raw->buff + 2, &len);
1623
1624 raw->len = len + len_h + 2;
1625
1626 if (raw->len - 1 > 4096) {
1627 trace(NULL, 2, "BINEX length error: len=%d\n", raw->len - 1);
1628 raw->nbyte = 0;
1629 return -1;
1630 }
1631 len_c = (raw->len - 1 < 128) ? 1 : 2;
1632
1633 if (fread(raw->buff + 6, 1, raw->len + len_c - 6, fp) < (size_t)(raw->len + len_c - 6)) {
1634 return -2;
1635 }
1636 raw->nbyte = 0;
1637
1638 /* decode BINEX message */
1639 return decode_bnx(raw);
1640}
1641
1642/*============================================================================
1643 * BINEX file reading functions (post-processing)
1644 *
1645 * Ported from upstream claslib/src/rcv/binex.c lines 1305-1601.
1646 *===========================================================================*/
1647
1648#define NINCOBS 262144 /* incremental number of obs data */
1649
1650/* set string without padding ------------------------------------------------*/
1651static void setstr_bnx(char* dst, const char* src, int n) {
1652 char* p = dst;
1653 const char* q = src;
1654 while (*q && q < src + n) {
1655 *p++ = *q++;
1656 }
1657 *p-- = '\0';
1658 while (p >= dst && *p == ' ') {
1659 *p-- = '\0';
1660 }
1661}
1662/* save cycle-slip flags -----------------------------------------------------*/
1663static void saveslips(unsigned char slips[][NFREQ], obsd_t* data) {
1664 int i;
1665 for (i = 0; i < NFREQ; i++) {
1666 if (data->LLI[i] & 1) {
1667 slips[data->sat - 1][i] |= 1;
1668 }
1669 }
1670}
1671/* restore cycle-slip flags --------------------------------------------------*/
1672static void restslips(unsigned char slips[][NFREQ], obsd_t* data) {
1673 int i;
1674 for (i = 0; i < NFREQ; i++) {
1675 if (slips[data->sat - 1][i] & 1) {
1676 data->LLI[i] |= 1;
1677 }
1678 slips[data->sat - 1][i] = 0;
1679 }
1680}
1681/* add observation data ------------------------------------------------------*/
1682static int addobsdata(obs_t* obs, const obsd_t* data) {
1683 obsd_t* obs_data;
1684
1685 if (obs->nmax <= obs->n) {
1686 if (obs->nmax <= 0) {
1687 obs->nmax = NINCOBS;
1688 } else {
1689 obs->nmax *= 2;
1690 }
1691 if (!(obs_data = (obsd_t*)realloc(obs->data, sizeof(obsd_t) * obs->nmax))) {
1692 trace(NULL, 1, "addobsdata: memalloc error n=%dx%d\n", (int)sizeof(obsd_t), obs->nmax);
1693 free(obs->data);
1694 obs->data = NULL;
1695 obs->n = obs->nmax = 0;
1696 return -1;
1697 }
1698 obs->data = obs_data;
1699 }
1700 obs->data[obs->n++] = *data;
1701 return 1;
1702}
1703/* add ephemeris data --------------------------------------------------------*/
1704static int add_eph(nav_t* nav, const eph_t* eph) {
1705 eph_t* nav_eph;
1706
1707 if (nav->nmax <= nav->n) {
1708 nav->nmax += 1024;
1709 if (!(nav_eph = (eph_t*)realloc(nav->eph, sizeof(eph_t) * nav->nmax))) {
1710 trace(NULL, 1, "add_eph: memalloc error n=%d\n", nav->nmax);
1711 free(nav->eph);
1712 nav->eph = NULL;
1713 nav->n = nav->nmax = 0;
1714 return 0;
1715 }
1716 nav->eph = nav_eph;
1717 }
1718 nav->eph[nav->n++] = *eph;
1719 return 1;
1720}
1721/* add GLONASS ephemeris data ------------------------------------------------*/
1722static int add_geph(nav_t* nav, const geph_t* geph) {
1723 geph_t* nav_geph;
1724
1725 if (nav->ngmax <= nav->ng) {
1726 nav->ngmax += 1024;
1727 if (!(nav_geph = (geph_t*)realloc(nav->geph, sizeof(geph_t) * nav->ngmax))) {
1728 trace(NULL, 1, "add_geph: memalloc error n=%d\n", nav->ngmax);
1729 free(nav->geph);
1730 nav->geph = NULL;
1731 nav->ng = nav->ngmax = 0;
1732 return 0;
1733 }
1734 nav->geph = nav_geph;
1735 }
1736 nav->geph[nav->ng++] = *geph;
1737 return 1;
1738}
1739/* add SBAS ephemeris data ---------------------------------------------------*/
1740static int add_seph(nav_t* nav, const seph_t* seph) {
1741 seph_t* nav_seph;
1742
1743 if (nav->nsmax <= nav->ns) {
1744 nav->nsmax += 1024;
1745 if (!(nav_seph = (seph_t*)realloc(nav->seph, sizeof(seph_t) * nav->nsmax))) {
1746 trace(NULL, 1, "add_seph: memalloc error n=%d\n", nav->nsmax);
1747 free(nav->seph);
1748 nav->seph = NULL;
1749 nav->ns = nav->nsmax = 0;
1750 return 0;
1751 }
1752 nav->seph = nav_seph;
1753 }
1754 nav->seph[nav->ns++] = *seph;
1755 return 1;
1756}
1757/* read BINEX file pointer ---------------------------------------------------*/
1758static int readbnxfp(FILE* fp, gtime_t ts, gtime_t te, double tint, const char* opt, int flag, int index, char* type,
1759 obs_t* obs, nav_t* nav, sta_t* sta, const prcopt_t* popt) {
1760 unsigned char slips[MAXSAT][NFREQ] = {{0}};
1761 int stat, data, dec_type, sys, sat, prn, mask, i;
1762 uint32_t len;
1763 int len_h, len_c;
1764 static raw_t raw;
1765
1766 memset(&raw, '\0', sizeof(raw));
1767 init_raw(&raw, STRFMT_BINEX);
1768 strcpy(raw.opt, opt);
1769 mask = popt->navsys;
1770
1771 while (1) {
1772 if ((data = fgetc(fp)) == EOF) {
1773 break;
1774 }
1775 if (!sync_bnx(raw.buff, (unsigned char)data)) {
1776 continue;
1777 }
1778
1779 if (fread(raw.buff + 2, 1, 4, fp) < 4) {
1780 break;
1781 }
1782
1783 len_h = getbnxi(raw.buff + 2, &len);
1784 raw.len = len + len_h + 2;
1785
1786 if (raw.len - 1 > 4096) {
1787 trace(NULL, 2, "binex length error: len=%d\n", raw.len - 1);
1788 raw.nbyte = 0;
1789 continue;
1790 }
1791 len_c = (raw.len - 1 < 128) ? 1 : 2;
1792
1793 if (raw.len + len_c - 6 < 1) {
1794 trace(NULL, 2, "binex length error: len=%d\n", raw.len - 1);
1795 raw.nbyte = 0;
1796 continue;
1797 }
1798 if (fread(raw.buff + 6, 1, raw.len + len_c - 6, fp) < (size_t)(raw.len + len_c - 6)) {
1799 break;
1800 }
1801 raw.nbyte = 0;
1802
1803 if ((dec_type = decode_bnx(&raw)) >= 1) {
1804 switch (dec_type) {
1805 case 1: /* observation data */
1806 for (i = 0; i < raw.obs.n; i++) {
1807 saveslips(slips, raw.obs.data + i);
1808 }
1809 if (raw.obs.n > 0 && !screent(raw.obs.data[0].time, ts, te, tint)) {
1810 continue;
1811 }
1812
1813 for (i = 0; i < raw.obs.n; i++) {
1814 restslips(slips, raw.obs.data + i);
1815 raw.obs.data[i].rcv = (unsigned char)index;
1816
1817 if (!(satsys(raw.obs.data[i].sat, NULL) & mask)) {
1818 continue;
1819 }
1820
1821 if ((stat = addobsdata(obs, raw.obs.data + i)) < 0) {
1822 break;
1823 }
1824 }
1825 break;
1826 case 2: /* ephemeris data */
1827 sat = raw.ephsat;
1828 sys = satsys(sat, &prn);
1829
1830 if (!(sys & mask)) {
1831 break;
1832 }
1833
1834 switch (sys) {
1835 case SYS_GLO:
1836 stat = add_geph(nav, &raw.nav.geph[prn - 1]);
1837 break;
1838 case SYS_SBS:
1839 stat = add_seph(nav, &raw.nav.seph[prn - MINPRNSBS]);
1840 break;
1841 default:
1842 stat = add_eph(nav, &raw.nav.eph[sat - 1]);
1843 break;
1844 }
1845 if (!stat) {
1846 free_raw(&raw);
1847 return 0;
1848 }
1849 break;
1850 }
1851 }
1852 }
1853 free_raw(&raw);
1854 return 1;
1855}
1856/* read BINEX file -----------------------------------------------------------*/
1857static int readbnxfile(const char* file, gtime_t ts, gtime_t te, double tint, const char* opt, int flag, int index,
1858 char* type, obs_t* obs, nav_t* nav, sta_t* sta, const prcopt_t* popt) {
1859 FILE* fp;
1860 int cstat, stat;
1861 char tmpfile[1024];
1862
1863 trace(NULL, 3, "readbnxfile: file=%s flag=%d index=%d\n", file, flag, index);
1864
1865 if (sta) {
1866 *sta->name = '\0';
1867 *sta->marker = '\0';
1868 *sta->antdes = '\0';
1869 *sta->antsno = '\0';
1870 *sta->rectype = '\0';
1871 *sta->recver = '\0';
1872 *sta->recsno = '\0';
1873 sta->antsetup = sta->itrf = sta->deltype = 0;
1874 sta->hgt = 0.0;
1875 }
1876 /* uncompress file */
1877 if ((cstat = rtk_uncompress(file, tmpfile)) < 0) {
1878 trace(NULL, 2, "binex file uncompact error: %s\n", file);
1879 return 0;
1880 }
1881 if (!(fp = fopen(cstat ? tmpfile : file, "rb"))) {
1882 trace(NULL, 2, "binex file open error: %s\n", cstat ? tmpfile : file);
1883 return 0;
1884 }
1885 stat = readbnxfp(fp, ts, te, tint, opt, flag, index, type, obs, nav, sta, popt);
1886
1887 fclose(fp);
1888 if (cstat) {
1889 remove(tmpfile);
1890 }
1891
1892 return stat;
1893}
1894/* read BINEX observation/navigation data --------------------------------------
1895 * read BINEX obs/nav data from file
1896 * args : char *file I BINEX file name
1897 * int rcv I receiver number (1:rover, 2:base)
1898 * gtime_t ts I start time (ts.time==0: from beginning)
1899 * gtime_t te I end time (te.time==0: to end)
1900 * double tint I observation interval (0: all)
1901 * char *opt I decode options
1902 * obs_t *obs IO observation data
1903 * nav_t *nav IO navigation data
1904 * sta_t *sta IO station info (NULL: not output)
1905 * prcopt_t *popt I processing options (for navsys mask)
1906 * return : status (1:ok, 0:no data, -1:error)
1907 *-----------------------------------------------------------------------------*/
1908extern int readbnxt(const char* file, int rcv, gtime_t ts, gtime_t te, double tint, const char* opt, obs_t* obs,
1909 nav_t* nav, sta_t* sta, const prcopt_t* popt) {
1910 int i, n, stat = 0;
1911 const char* p;
1912 char type = ' ', *files[MAXEXFILE] = {0};
1913
1914 trace(NULL, 3, "readbnxt: file=%s rcv=%d\n", file, rcv);
1915
1916 if (!*file) {
1917 return readbnxfp(stdin, ts, te, tint, opt, 0, 1, &type, obs, nav, sta, popt);
1918 }
1919 for (i = 0; i < MAXEXFILE; i++) {
1920 if (!(files[i] = (char*)malloc(1024))) {
1921 for (i--; i >= 0; i--) {
1922 free(files[i]);
1923 }
1924 return -1;
1925 }
1926 }
1927 /* expand wild-card */
1928 if ((n = expath(file, files, MAXEXFILE)) <= 0) {
1929 for (i = 0; i < MAXEXFILE; i++) {
1930 free(files[i]);
1931 }
1932 return 0;
1933 }
1934 for (i = 0; i < n && stat >= 0; i++) {
1935 stat = readbnxfile(files[i], ts, te, tint, opt, 0, rcv, &type, obs, nav, sta, popt);
1936 }
1937 /* if station name empty, set 4-char name from file head */
1938 if (sta) {
1939 if (!(p = strrchr(file, FILEPATHSEP))) {
1940 p = file - 1;
1941 }
1942 if (!*sta->name) {
1943 setstr_bnx(sta->name, p + 1, 4);
1944 }
1945 }
1946 for (i = 0; i < MAXEXFILE; i++) {
1947 free(files[i]);
1948 }
1949
1950 return stat;
1951}
uint16_t rtk_crc16(const uint8_t *buff, int len)
Compute CRC-16 parity for BINEX and NVS.
Definition mrtk_bits.c:199
uint32_t getbitu(const uint8_t *buff, int pos, int len)
Extract unsigned bits from byte data.
Definition mrtk_bits.c:99
int32_t getbits(const uint8_t *buff, int pos, int len)
Extract signed bits from byte data.
Definition mrtk_bits.c:107
MRTKLIB Bits Module — Binary bit operations and CRC functions.
#define D2R
Definition mrtk_coords.c:36
void pos2ecef(const double *pos, double *r)
Transform geodetic position to ECEF position.
#define CLIGHT
Definition mrtk_coords.c:41
#define MAXSAT
Definition mrtk_coords.c:45
MRTKLIB Coordinates Module — Coordinate transformations and geometry.
int satsys(int sat, int *prn)
Definition mrtk_nav.c:117
static int eph_sel[]
Definition mrtk_eph.c:450
#define SYS_GPS
Definition mrtk_eph.c:65
#define SYS_SBS
Definition mrtk_eph.c:66
#define SYS_QZS
Definition mrtk_eph.c:69
#define SYS_IRN
Definition mrtk_eph.c:71
#define SYS_CMP
Definition mrtk_eph.c:70
#define SYS_GAL
Definition mrtk_eph.c:68
#define SYS_GLO
Definition mrtk_eph.c:67
MRTKLIB Broadcast Ephemeris Module — Satellite orbit/clock types and Kepler/GLONASS/SBAS orbit comput...
struct nav_s nav_t
Definition mrtk_eph.h:40
double code2freq(int sys, uint8_t code, int fcn)
Definition mrtk_obs.c:236
#define SNR_UNIT
#define CODE_L5C
#define CODE_L5Q
#define CODE_L2N
#define CODE_L2Q
#define CODE_L6C
#define CODE_L1S
#define CODE_L7Z
#define CODE_L5I
#define CODE_L7P
#define CODE_L2X
#define CODE_L3X
#define CODE_L6E
#define CODE_L1L
#define MAXOBS
#define CODE_L5X
#define CODE_L7X
#define CODE_L2P
#define CODE_L2I
#define CODE_L6S
#define CODE_L5B
#define CODE_L1C
#define MAXANT
#define CODE_L6I
#define CODE_L2C
#define CODE_L7I
#define CODE_L4X
#define CODE_L6X
#define CODE_NONE
#define CODE_L6D
#define CODE_L9C
#define CODE_L9A
#define CODE_L4B
#define CODE_L1Y
#define CODE_L8Q
#define CODE_L5P
#define CODE_L3Q
#define CODE_L5D
#define CODE_L8P
#define CODE_L3I
#define CODE_L1B
#define CODE_L7D
#define CODE_L2S
#define CODE_L9X
#define CODE_L6L
#define CODE_L6P
#define CODE_L7Q
#define CODE_L1W
#define CODE_L6B
#define CODE_L5Z
#define CODE_L8X
#define CODE_L1M
#define CODE_L1N
#define CODE_L2W
#define CODE_L2L
#define CODE_L9B
#define CODE_L1Z
#define CODE_L1D
#define CODE_L5A
#define MINPRNGLO
#define CODE_L2D
#define CODE_L2Y
#define CODE_L8I
#define CODE_L1P
#define CODE_L6A
#define MAXEXFILE
#define CODE_L2M
#define CODE_L8D
#define CODE_L6Q
#define CODE_L6Z
#define CODE_L1X
#define CODE_L4A
#define CODE_L1A
static const double range[4]
Definition mrtk_geoid.c:37
void matcpy(double *A, const double *B, int n, int m)
Copy matrix.
Definition mrtk_mat.c:205
MRTKLIB Matrix Module — Matrix/vector operations and estimation.
int satno(int sys, int prn)
Convert satellite system+prn/slot number to satellite number.
Definition mrtk_nav.c:58
MRTKLIB Navigation Module — Navigation data types and satellite/nav utility functions.
int getcodepri(int sys, uint8_t code, const char *opt)
Get code priority for multiple codes in a frequency.
Definition mrtk_obs.c:276
int code2freq_idx(int sys, uint8_t code)
Convert system and obs code to frequency index (obsdef-based).
Definition mrtk_obs.c:225
int screent(gtime_t time, gtime_t ts, gtime_t te, double tint)
Screen data by time range and interval.
Definition mrtk_obs.c:424
MRTKLIB Observation Module — Observation data types and utility functions.
MRTKLIB Options Module — Processing and solution option types.
static int readbnxfile(const char *file, gtime_t ts, gtime_t te, double tint, const char *opt, int flag, int index, char *type, obs_t *obs, nav_t *nav, sta_t *sta, const prcopt_t *popt)
static int decode_bnx_01_03(raw_t *raw, uint8_t *buff, int len)
static int add_geph(nav_t *nav, const geph_t *geph)
static int sisaindex(double value)
int input_bnx(raw_t *raw, uint8_t data)
#define U1(p)
static gtime_t adjweek(gtime_t time, double tow)
static int sync_bnx(uint8_t *buff, uint8_t data)
static int add_seph(nav_t *nav, const seph_t *seph)
static int uraindex(double value)
static int decode_bnx_00(raw_t *raw, uint8_t *buff, int len)
static int getbnxi(uint8_t *p, uint32_t *val)
int input_bnxf(raw_t *raw, FILE *fp)
static gtime_t adjday(gtime_t time, double tod)
static int decode_bnx_7d(raw_t *raw, uint8_t *buff, int len)
static int readbnxfp(FILE *fp, gtime_t ts, gtime_t te, double tint, const char *opt, int flag, int index, char *type, obs_t *obs, nav_t *nav, sta_t *sta, const prcopt_t *popt)
static int decode_bnx_01_01(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_7f_04(raw_t *raw, uint8_t *buff, int len)
#define BNXSYNC2
static int decode_bnx_01_06(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_7f_03(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_01(raw_t *raw, uint8_t *buff, int len)
static uint8_t csum8(const uint8_t *buff, int len)
static int decode_bnx_01_05(raw_t *raw, uint8_t *buff, int len)
static int add_eph(nav_t *nav, const eph_t *eph)
static int decode_bnx_01_02(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_01_04(raw_t *raw, uint8_t *buff, int len)
#define MIN(x, y)
#define MINPRNSBS
static int decode_bnx_7f_05(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_01_07(raw_t *raw, uint8_t *buff, int len)
static double bds_tgd(int tgd)
static int decode_bnx(raw_t *raw)
static uint8_t * decode_bnx_7f_05_obs(raw_t *raw, uint8_t *buff, int sat, int nobs, obsd_t *data)
static int decode_bnx_7f_01(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_7f_02(raw_t *raw, uint8_t *buff, int len)
static void setstr_bnx(char *dst, const char *src, int n)
#define SQR(x)
static int decode_bnx_7f_00(raw_t *raw, uint8_t *buff, int len)
static int addobsdata(obs_t *obs, const obsd_t *data)
static int decode_bnx_7f(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_03(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_01_14(raw_t *raw, uint8_t *buff, int len)
int readbnxt(const char *file, int rcv, gtime_t ts, gtime_t te, double tint, const char *opt, obs_t *obs, nav_t *nav, sta_t *sta, const prcopt_t *popt)
Read BINEX observation/navigation data from file(s).
#define I1(p)
static void saveslips(unsigned char slips[][5], obsd_t *data)
static int decode_bnx_02(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_7e(raw_t *raw, uint8_t *buff, int len)
static int decode_bnx_01_00(raw_t *raw, uint8_t *buff, int len)
static void restslips(unsigned char slips[][5], obsd_t *data)
#define R8(p)
#define U4(p)
#define I4(p)
#define R4(p)
#define U2(p)
#define P2_31
Definition mrtk_rcvraw.c:56
void free_raw(raw_t *raw)
Free receiver raw data control struct.
int init_raw(raw_t *raw, int format)
Initialize receiver raw data control struct.
#define SC2RAD
Definition mrtk_rcvraw.c:33
MRTKLIB Receiver Raw Data Module — Receiver raw data types and decoder functions for various GNSS rec...
#define STRFMT_BINEX
Definition mrtk_rcvraw.h:59
#define NINCOBS
Definition mrtk_rinex.c:76
static const double ura_eph[]
Definition mrtk_rinex.c:84
MRTKLIB RTCM Module — RTCM message types and functions.
#define FILEPATHSEP
Definition mrtk_sys.c:48
int expath(const char *path, char *paths[], int nmax)
Expand file path with wild-card (*) in file.
Definition mrtk_sys.c:96
int rtk_uncompress(const char *file, char *uncfile)
Uncompress file (gzip/zip/tar/Hatanaka).
Definition mrtk_sys.c:367
MRTKLIB System Module — OS/filesystem utility functions.
gtime_t epoch2time(const double *ep)
Convert calendar day/time to gtime_t struct.
Definition mrtk_time.c:113
gtime_t gpst2time(int week, double sec)
Convert GPS week/tow to gtime_t.
Definition mrtk_time.c:165
void time2epoch(gtime_t t, double *ep)
Convert gtime_t struct to calendar day/time.
Definition mrtk_time.c:136
double timediff(gtime_t t1, gtime_t t2)
Compute time difference (t1 - t2).
Definition mrtk_time.c:279
double time2gpst(gtime_t t, int *week)
Convert gtime_t to GPS week/tow.
Definition mrtk_time.c:181
gtime_t timeadd(gtime_t t, double sec)
Add seconds to gtime_t.
Definition mrtk_time.c:265
char * time_str(gtime_t t, int n)
Get time string (not reentrant).
Definition mrtk_time.c:530
static const double gpst0[]
GPS time reference epoch.
Definition mrtk_time.c:42
gtime_t utc2gpst(gtime_t t)
Convert UTC to GPS time considering leap seconds.
Definition mrtk_time.c:440
MRTKLIB Time Module — GNSS time types and conversion functions.
void trace(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message.
Definition mrtk_trace.c:78
MRTKLIB Trace Module — debug trace and logging functions.
GPS/GAL/QZS/BDS/IRN broadcast ephemeris type.
Definition mrtk_eph.h:77
double OMG0
Definition mrtk_eph.h:90
double omg
Definition mrtk_eph.h:90
int sat
Definition mrtk_eph.h:78
gtime_t ttr
Definition mrtk_eph.h:88
double OMGd
Definition mrtk_eph.h:90
double f1
Definition mrtk_eph.h:94
double f0
Definition mrtk_eph.h:94
int svh
Definition mrtk_eph.h:81
double e
Definition mrtk_eph.h:90
double idot
Definition mrtk_eph.h:90
double M0
Definition mrtk_eph.h:90
double A
Definition mrtk_eph.h:90
double cis
Definition mrtk_eph.h:91
int flag
Definition mrtk_eph.h:86
gtime_t toe
Definition mrtk_eph.h:88
double fit
Definition mrtk_eph.h:93
int week
Definition mrtk_eph.h:82
gtime_t toc
Definition mrtk_eph.h:88
double cic
Definition mrtk_eph.h:91
double tgd[6]
Definition mrtk_eph.h:95
double cus
Definition mrtk_eph.h:91
double cuc
Definition mrtk_eph.h:91
double toes
Definition mrtk_eph.h:92
int code
Definition mrtk_eph.h:83
int type
Definition mrtk_eph.h:100
double crs
Definition mrtk_eph.h:91
double i0
Definition mrtk_eph.h:90
int iode
Definition mrtk_eph.h:79
int sva
Definition mrtk_eph.h:80
double deln
Definition mrtk_eph.h:90
double crc
Definition mrtk_eph.h:91
double f2
Definition mrtk_eph.h:94
int iodc
Definition mrtk_eph.h:79
GLONASS broadcast ephemeris type.
Definition mrtk_eph.h:111
double vel[3]
Definition mrtk_eph.h:121
double dtaun
Definition mrtk_eph.h:124
gtime_t toe
Definition mrtk_eph.h:118
double pos[3]
Definition mrtk_eph.h:120
int iode
Definition mrtk_eph.h:113
double gamn
Definition mrtk_eph.h:123
double acc[3]
Definition mrtk_eph.h:122
int age
Definition mrtk_eph.h:117
int svh
Definition mrtk_eph.h:115
double taun
Definition mrtk_eph.h:123
gtime_t tof
Definition mrtk_eph.h:119
int sat
Definition mrtk_eph.h:112
int frq
Definition mrtk_eph.h:114
GNSS time representation.
Definition mrtk_time.h:49
time_t time
Definition mrtk_time.h:50
int ng
Definition mrtk_nav.h:394
int glo_fcn[32]
Definition mrtk_nav.h:426
seph_t * seph
Definition mrtk_nav.h:408
geph_t * geph
Definition mrtk_nav.h:407
eph_t * eph
Definition mrtk_nav.h:400
int nsmax
Definition mrtk_nav.h:395
int ngmax
Definition mrtk_nav.h:394
int nmax
Definition mrtk_nav.h:393
int ns
Definition mrtk_nav.h:395
int n
Definition mrtk_nav.h:393
Observation data collection.
Definition mrtk_obs.h:59
obsd_t * data
Definition mrtk_obs.h:61
int nmax
Definition mrtk_obs.h:60
int n
Definition mrtk_obs.h:60
Observation data record.
Definition mrtk_obs.h:44
float D[5+5]
Definition mrtk_obs.h:52
gtime_t time
Definition mrtk_obs.h:45
uint8_t sat
Definition mrtk_obs.h:46
uint8_t LLI[5+5]
Definition mrtk_obs.h:48
double L[5+5]
Definition mrtk_obs.h:50
uint8_t rcv
Definition mrtk_obs.h:46
double P[5+5]
Definition mrtk_obs.h:51
uint16_t SNR[5+5]
Definition mrtk_obs.h:47
uint8_t code[5+5]
Definition mrtk_obs.h:49
int navsys
Definition mrtk_opt.h:175
Receiver raw data control type.
Definition mrtk_rcvraw.h:78
nav_t nav
Definition mrtk_rcvraw.h:83
int ephset
Definition mrtk_rcvraw.h:86
int outtype
obs_t obs
Definition mrtk_rcvraw.h:81
int len
Definition mrtk_rcvraw.h:96
uint8_t buff[MAXRAWLEN]
char msgtype[256]
Definition mrtk_rcvraw.h:88
int nbyte
Definition mrtk_rcvraw.h:95
char opt[256]
sta_t sta
Definition mrtk_rcvraw.h:84
int ephsat
Definition mrtk_rcvraw.h:85
gtime_t time
Definition mrtk_rcvraw.h:79
SBAS ephemeris type.
Definition mrtk_eph.h:130
int sva
Definition mrtk_eph.h:134
double pos[3]
Definition mrtk_eph.h:136
double vel[3]
Definition mrtk_eph.h:137
double acc[3]
Definition mrtk_eph.h:138
gtime_t tof
Definition mrtk_eph.h:133
double af0
Definition mrtk_eph.h:139
int sat
Definition mrtk_eph.h:131
gtime_t t0
Definition mrtk_eph.h:132
int svh
Definition mrtk_eph.h:135
int itrf
Definition mrtk_nav.h:378
double pos[3]
Definition mrtk_nav.h:380
char antsno[MAXANT]
Definition mrtk_nav.h:373
char recsno[MAXANT]
Definition mrtk_nav.h:376
int deltype
Definition mrtk_nav.h:379
char recver[MAXANT]
Definition mrtk_nav.h:375
double hgt
Definition mrtk_nav.h:382
double del[3]
Definition mrtk_nav.h:381
char rectype[MAXANT]
Definition mrtk_nav.h:374
char name[MAXANT]
Definition mrtk_nav.h:370
int antsetup
Definition mrtk_nav.h:377
char marker[MAXANT]
Definition mrtk_nav.h:371
char antdes[MAXANT]
Definition mrtk_nav.h:372
#define malloc(x)
Definition toml.c:52
#define free(x)
Definition toml.c:53