MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_rcvraw.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_rcvraw.c : receiver raw data functions
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 "mrtklib/mrtk_rcvraw.h"
17
18#include <math.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "mrtklib/mrtk_bits.h"
23#include "mrtklib/mrtk_eph.h"
24#include "mrtklib/mrtk_l6.h"
25#include "mrtklib/mrtk_madoca.h"
26#include "mrtklib/mrtk_nav.h"
27#include "mrtklib/mrtk_obs.h"
28#include "mrtklib/mrtk_rtcm.h"
29#include "mrtklib/mrtk_time.h"
30#include "mrtklib/mrtk_trace.h"
31
32/* Local constants (duplicated from rtklib.h to avoid dependency) */
33#define SC2RAD 3.1415926535898 /* semi-circle to radian (IS-GPS) */
34
35#define SYS_GPS 0x01
36#define SYS_GLO 0x04
37#define SYS_GAL 0x08
38#define SYS_QZS 0x10
39#define SYS_CMP 0x20
40#define SYS_IRN 0x40
41
42/* Power-of-2 constants from rtklib.h */
43#define P2_5 0.03125 /* 2^-5 */
44#define P2_6 0.015625 /* 2^-6 */
45#define P2_11 4.882812500000000E-04 /* 2^-11 */
46#define P2_15 3.051757812500000E-05 /* 2^-15 */
47#define P2_17 7.629394531250000E-06 /* 2^-17 */
48#define P2_19 1.907348632812500E-06 /* 2^-19 */
49#define P2_20 9.536743164062500E-07 /* 2^-20 */
50#define P2_21 4.768371582031250E-07 /* 2^-21 */
51#define P2_23 1.192092895507810E-07 /* 2^-23 */
52#define P2_24 5.960464477539063E-08 /* 2^-24 */
53#define P2_27 7.450580596923828E-09 /* 2^-27 */
54#define P2_29 1.862645149230957E-09 /* 2^-29 */
55#define P2_30 9.313225746154785E-10 /* 2^-30 */
56#define P2_31 4.656612873077393E-10 /* 2^-31 */
57#define P2_32 2.328306436538696E-10 /* 2^-32 */
58#define P2_33 1.164153218269348E-10 /* 2^-33 */
59#define P2_35 2.910383045673370E-11 /* 2^-35 */
60#define P2_38 3.637978807091710E-12 /* 2^-38 */
61#define P2_40 9.094947017729280E-13 /* 2^-40 */
62#define P2_43 1.136868377216160E-13 /* 2^-43 */
63#define P2_50 8.881784197001252E-16 /* 2^-50 */
64#define P2_55 2.775557561562891E-17 /* 2^-55 */
65
66/* Forward declarations for functions in rtklib (resolved at link time) */
67
68#define P2_8 0.00390625 /* 2^-8 */
69#define P2_9 0.001953125 /* 2^-9 */
70#define P2_14 6.103515625000000E-05 /* 2^-14 */
71#define P2_18 3.814697265625000E-06 /* 2^-18 */
72#define P2_28 3.725290298461914E-09 /* 2^-28 */
73#define P2_34 5.820766091346740E-11 /* 2^-34 */
74#define P2_41 4.547473508864641E-13 /* 2^-41 */
75#define P2_46 1.421085471520200E-14 /* 2^-46 */
76#define P2_51 4.440892098500626E-16 /* 2^-51 */
77#define P2_59 1.734723475976810E-18 /* 2^-59 */
78#define P2_66 1.355252715606881E-20 /* 2^-66 */
79#define P2_68 3.388131789017201E-21 /* 2^-68 */
80#define P2P11 2048.0 /* 2^11 */
81#define P2P12 4096.0 /* 2^12 */
82#define P2P14 16384.0 /* 2^14 */
83#define P2P15 32768.0 /* 2^15 */
84#define P2P16 65536.0 /* 2^16 */
85
86#define SQR(x) ((x) * (x))
87
88/* get two component bits ----------------------------------------------------*/
89static uint32_t getbitu2(const uint8_t* buff, int p1, int l1, int p2, int l2) {
90 return (getbitu(buff, p1, l1) << l2) + getbitu(buff, p2, l2);
91}
92static int32_t getbits2(const uint8_t* buff, int p1, int l1, int p2, int l2) {
93 if (getbitu(buff, p1, 1)) {
94 return (int32_t)((getbits(buff, p1, l1) << l2) + getbitu(buff, p2, l2));
95 } else {
96 return (int32_t)getbitu2(buff, p1, l1, p2, l2);
97 }
98}
99/* get three component bits --------------------------------------------------*/
100static uint32_t getbitu3(const uint8_t* buff, int p1, int l1, int p2, int l2, int p3, int l3) {
101 return (getbitu(buff, p1, l1) << (l2 + l3)) + (getbitu(buff, p2, l2) << l3) + getbitu(buff, p3, l3);
102}
103static int32_t getbits3(const uint8_t* buff, int p1, int l1, int p2, int l2, int p3, int l3) {
104 if (getbitu(buff, p1, 1)) {
105 return (int32_t)((getbits(buff, p1, l1) << (l2 + l3)) + (getbitu(buff, p2, l2) << l3) + getbitu(buff, p3, l3));
106 } else {
107 return (int32_t)getbitu3(buff, p1, l1, p2, l2, p3, l3);
108 }
109}
110/* merge two components ------------------------------------------------------*/
111static uint32_t merge_two_u(uint32_t a, uint32_t b, int n) { return (a << n) + b; }
112static int32_t merge_two_s(int32_t a, uint32_t b, int n) { return (int32_t)((a << n) + b); }
113/* get sign-magnitude bits ---------------------------------------------------*/
114static double getbitg(const uint8_t* buff, int pos, int len) {
115 double value = getbitu(buff, pos + 1, len - 1);
116 return getbitu(buff, pos, 1) ? -value : value;
117}
118/* decode NavIC/IRNSS ephemeris ----------------------------------------------*/
119static int decode_irn_eph(const uint8_t* buff, eph_t* eph) {
120 eph_t eph_irn = {0};
121 double tow1, tow2, toc, sqrtA;
122 int i, id1, id2, week;
123
124 trace(NULL, 4, "decode_irn_eph:\n");
125
126 i = 8; /* subframe 1 */
127 tow1 = getbitu(buff, i, 17) * 12.0;
128 i += 17 + 2;
129 id1 = getbitu(buff, i, 2);
130 i += 2 + 1;
131 week = getbitu(buff, i, 10);
132 i += 10;
133 eph_irn.f0 = getbits(buff, i, 22) * P2_31;
134 i += 22;
135 eph_irn.f1 = getbits(buff, i, 16) * P2_43;
136 i += 16;
137 eph_irn.f2 = getbits(buff, i, 8) * P2_55;
138 i += 8;
139 eph_irn.sva = getbitu(buff, i, 4);
140 i += 4;
141 toc = getbitu(buff, i, 16) * 16.0;
142 i += 16;
143 eph_irn.tgd[0] = getbits(buff, i, 8) * P2_31;
144 i += 8;
145 eph_irn.deln = getbits(buff, i, 22) * P2_41 * SC2RAD;
146 i += 22;
147 eph_irn.iode = getbitu(buff, i, 8);
148 i += 8 + 10;
149 eph_irn.svh = getbitu(buff, i, 2);
150 i += 2;
151 eph_irn.cuc = getbits(buff, i, 15) * P2_28;
152 i += 15;
153 eph_irn.cus = getbits(buff, i, 15) * P2_28;
154 i += 15;
155 eph_irn.cic = getbits(buff, i, 15) * P2_28;
156 i += 15;
157 eph_irn.cis = getbits(buff, i, 15) * P2_28;
158 i += 15;
159 eph_irn.crc = getbits(buff, i, 15) * 0.0625;
160 i += 15;
161 eph_irn.crs = getbits(buff, i, 15) * 0.0625;
162 i += 15;
163 eph_irn.idot = getbits(buff, i, 14) * P2_43 * SC2RAD;
164
165 i = 8 * 37 + 8; /* subframe 2 */
166 tow2 = getbitu(buff, i, 17) * 12.0;
167 i += 17 + 2;
168 id2 = getbitu(buff, i, 2);
169 i += 2 + 1;
170 eph_irn.M0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
171 i += 32;
172 eph_irn.toes = getbitu(buff, i, 16) * 16.0;
173 i += 16;
174 eph_irn.e = getbitu(buff, i, 32) * P2_33;
175 i += 32;
176 sqrtA = getbitu(buff, i, 32) * P2_19;
177 i += 32;
178 eph_irn.OMG0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
179 i += 32;
180 eph_irn.omg = getbits(buff, i, 32) * P2_31 * SC2RAD;
181 i += 32;
182 eph_irn.OMGd = getbits(buff, i, 22) * P2_41 * SC2RAD;
183 i += 22;
184 eph_irn.i0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
185
186 /* test subframe id, tow and consistency of toe and toc */
187 if (id1 != 0 || id2 != 1 || tow1 + 12.0 != tow2 || toc != eph_irn.toes) {
188 return 0;
189 }
190 eph_irn.A = SQR(sqrtA);
191 eph_irn.iodc = eph_irn.iode;
192 week = adjgpsweek(week);
193 eph_irn.week = week; /* week number consistent to toe */
194 eph_irn.toe = eph_irn.toc = gpst2time(eph_irn.week, eph_irn.toes);
195 if (tow1 < eph_irn.toes - 302400.0) {
196 week++;
197 } else if (tow1 > eph_irn.toes + 302400.0) {
198 week--;
199 }
200 eph_irn.ttr = gpst2time(week, tow1);
201 eph_irn.type = 0; /* ephemeris type = LNAV */
202 *eph = eph_irn;
203 return 1;
204}
205/* decode NavIC/IRNSS iono parameters ----------------------------------------*/
206static int decode_irn_ion(const uint8_t* buff, double* ion) {
207 int i, id3, id4;
208
209 trace(NULL, 4, "decode_irn_ion:\n");
210
211 /* subframe 3 and 4 message ids */
212 id3 = getbitu(buff, 8 * 37 * 2 + 30, 6);
213 id4 = getbitu(buff, 8 * 37 * 3 + 30, 6);
214
215 /* 11: eop and ionosphere coefficients */
216 if (id3 == 11) {
217 i = 8 * 37 * 2 + 174;
218 } else if (id4 == 11) {
219 i = 8 * 37 * 3 + 174;
220 } else {
221 return 0;
222 }
223
224 ion[0] = getbits(buff, i, 8) * P2_30;
225 i += 8;
226 ion[1] = getbits(buff, i, 8) * P2_27;
227 i += 8;
228 ion[2] = getbits(buff, i, 8) * P2_24;
229 i += 8;
230 ion[3] = getbits(buff, i, 8) * P2_24;
231 i += 8;
232 ion[4] = getbits(buff, i, 8) * P2P11;
233 i += 8;
234 ion[5] = getbits(buff, i, 8) * P2P14;
235 i += 8;
236 ion[6] = getbits(buff, i, 8) * P2P16;
237 i += 8;
238 ion[7] = getbits(buff, i, 8) * P2P16;
239 return 1;
240}
241/* decode NavIC/IRNSS UTC parameters -----------------------------------------*/
242static int decode_irn_utc(const uint8_t* buff, double* utc) {
243 int i, id3, id4;
244
245 trace(NULL, 4, "decode_irn_utc:\n");
246
247 /* subframe 3 and 4 message ids */
248 id3 = getbitu(buff, 8 * 37 * 2 + 30, 6);
249 id4 = getbitu(buff, 8 * 37 * 3 + 30, 6);
250
251 /* 9 or 26: utc and time sync parameters */
252 if (id3 == 9 || id3 == 26) {
253 i = 8 * 37 * 2 + 36;
254 } else if (id4 == 9 || id3 == 26) {
255 i = 8 * 37 * 3 + 36;
256 } else {
257 return 0;
258 }
259
260 utc[0] = getbits(buff, i, 16) * P2_35;
261 i += 16; /* A0 */
262 utc[1] = getbits(buff, i, 13) * P2_51;
263 i += 13; /* A1 */
264 utc[8] = getbits(buff, i, 7) * P2_68;
265 i += 7; /* A2 */
266 utc[4] = getbits(buff, i, 8);
267 i += 8; /* dt_LS */
268 utc[2] = getbitu(buff, i, 16) * 16.0;
269 i += 16; /* tot */
270 utc[3] = getbitu(buff, i, 10);
271 i += 10; /* WNt */
272 utc[5] = getbitu(buff, i, 10);
273 i += 10; /* WN_LSF */
274 utc[6] = getbitu(buff, i, 4);
275 i += 4; /* DN */
276 utc[7] = getbits(buff, i, 8); /* dt_LSF */
277 return 1;
278}
279/* decode NavIC/IRNSS navigation data ------------------------------------------
280 * decode NavIC/IRNSS navigation data (ref [6] 5.9-6)
281 * args : uint8_t *buff I NavIC/IRNSS subframe data (CRC checked)
282 * buff[ 0- 36]: subframe 1 (292 bits)
283 * buff[ 37- 73]: subframe 2
284 * buff[ 74-110]: subframe 3
285 * buff[111-147]: subframe 4
286 * eph_t *eph IO NavIC/IRNSS ephemeris (NULL: not output)
287 * double *ion IO NavIC/IRNSS iono parametgers (NULL: not output)
288 * ion[0-3]: alpha_0,...,alpha_3
289 * ion[4-7]: beta_0,...,beta_3
290 * double *utc IO NavIC/IRNSS UTC parametgers (NULL: not output)
291 * utc[0-3]: A0,A1,tot,WNt
292 * utc[4-7]: dt_LS,WN_LSF,DN,dt_LSF
293 * utc[8] : A2
294 * return : status (1:ok,0:error)
295 *-----------------------------------------------------------------------------*/
296extern int decode_irn_nav(const uint8_t* buff, eph_t* eph, double* ion, double* utc) {
297 trace(NULL, 4, "decode_irn_nav:\n");
298
299 if (eph && !decode_irn_eph(buff, eph)) {
300 return 0;
301 }
302 if (ion && !decode_irn_ion(buff, ion)) {
303 return 0;
304 }
305 if (utc && !decode_irn_utc(buff, utc)) {
306 return 0;
307 }
308 return 1;
309}
310/* decode Galileo I/NAV ephemeris --------------------------------------------*/
311static int decode_gal_inav_eph(const uint8_t* buff, eph_t* eph) {
312 eph_t eph_gal = {0};
313 double tow, toc, tt, sqrtA;
314 int i, week, svid, e5b_hs, e1b_hs, e5b_dvs, e1b_dvs, type[6], iod_nav[4];
315
316 trace(NULL, 4, "decode_gal_inav_eph:\n");
317
318 i = 128; /* word type 1 */
319 type[0] = getbitu(buff, i, 6);
320 i += 6;
321 iod_nav[0] = getbitu(buff, i, 10);
322 i += 10;
323 eph_gal.toes = getbitu(buff, i, 14) * 60.0;
324 i += 14;
325 eph_gal.M0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
326 i += 32;
327 eph_gal.e = getbitu(buff, i, 32) * P2_33;
328 i += 32;
329 sqrtA = getbitu(buff, i, 32) * P2_19;
330
331 i = 128 * 2; /* word type 2 */
332 type[1] = getbitu(buff, i, 6);
333 i += 6;
334 iod_nav[1] = getbitu(buff, i, 10);
335 i += 10;
336 eph_gal.OMG0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
337 i += 32;
338 eph_gal.i0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
339 i += 32;
340 eph_gal.omg = getbits(buff, i, 32) * P2_31 * SC2RAD;
341 i += 32;
342 eph_gal.idot = getbits(buff, i, 14) * P2_43 * SC2RAD;
343
344 i = 128 * 3; /* word type 3 */
345 type[2] = getbitu(buff, i, 6);
346 i += 6;
347 iod_nav[2] = getbitu(buff, i, 10);
348 i += 10;
349 eph_gal.OMGd = getbits(buff, i, 24) * P2_43 * SC2RAD;
350 i += 24;
351 eph_gal.deln = getbits(buff, i, 16) * P2_43 * SC2RAD;
352 i += 16;
353 eph_gal.cuc = getbits(buff, i, 16) * P2_29;
354 i += 16;
355 eph_gal.cus = getbits(buff, i, 16) * P2_29;
356 i += 16;
357 eph_gal.crc = getbits(buff, i, 16) * P2_5;
358 i += 16;
359 eph_gal.crs = getbits(buff, i, 16) * P2_5;
360 i += 16;
361 eph_gal.sva = getbitu(buff, i, 8);
362
363 i = 128 * 4; /* word type 4 */
364 type[3] = getbitu(buff, i, 6);
365 i += 6;
366 iod_nav[3] = getbitu(buff, i, 10);
367 i += 10;
368 svid = getbitu(buff, i, 6);
369 i += 6;
370 eph_gal.cic = getbits(buff, i, 16) * P2_29;
371 i += 16;
372 eph_gal.cis = getbits(buff, i, 16) * P2_29;
373 i += 16;
374 toc = getbitu(buff, i, 14) * 60.0;
375 i += 14;
376 eph_gal.f0 = getbits(buff, i, 31) * P2_34;
377 i += 31;
378 eph_gal.f1 = getbits(buff, i, 21) * P2_46;
379 i += 21;
380 eph_gal.f2 = getbits(buff, i, 6) * P2_59;
381
382 i = 128 * 5; /* word type 5 */
383 type[4] = getbitu(buff, i, 6);
384 i += 6 + 11 + 11 + 14 + 5;
385 eph_gal.tgd[0] = getbits(buff, i, 10) * P2_32;
386 i += 10; /* BGD E5a/E1 */
387 eph_gal.tgd[1] = getbits(buff, i, 10) * P2_32;
388 i += 10; /* BGD E5b/E1 */
389 e5b_hs = getbitu(buff, i, 2);
390 i += 2;
391 e1b_hs = getbitu(buff, i, 2);
392 i += 2;
393 e5b_dvs = getbitu(buff, i, 1);
394 i += 1;
395 e1b_dvs = getbitu(buff, i, 1);
396 i += 1;
397 week = getbitu(buff, i, 12);
398 i += 12; /* gst-week */
399 tow = getbitu(buff, i, 20);
400
401 /* test word types */
402 if (type[0] != 1 || type[1] != 2 || type[2] != 3 || type[3] != 4 || type[4] != 5) {
403 trace(NULL, 3, "decode_gal_inav error: type=%d %d %d %d %d\n", type[0], type[1], type[2], type[3], type[4]);
404 return 0;
405 }
406 /* test consistency of iod_nav */
407 if (iod_nav[0] != iod_nav[1] || iod_nav[0] != iod_nav[2] || iod_nav[0] != iod_nav[3]) {
408 trace(NULL, 3, "decode_gal_inav error: iod_nav=%d %d %d %d\n", iod_nav[0], iod_nav[1], iod_nav[2], iod_nav[3]);
409 return 0;
410 }
411 if (!(eph_gal.sat = satno(SYS_GAL, svid))) {
412 trace(NULL, 2, "decode_gal_inav svid error: svid=%d\n", svid);
413 return 0;
414 }
415 eph_gal.A = sqrtA * sqrtA;
416 eph_gal.iode = eph_gal.iodc = iod_nav[0];
417 eph_gal.svh = (e5b_hs << 7) | (e5b_dvs << 6) | (e1b_hs << 1) | e1b_dvs;
418 eph_gal.ttr = gst2time(week, tow);
419 tt = timediff(gst2time(week, eph_gal.toes), eph_gal.ttr);
420 if (tt > 302400.0) {
421 week--; /* week consistent with toe */
422 } else if (tt < -302400.0) {
423 week++;
424 }
425 eph_gal.toe = gst2time(week, eph_gal.toes);
426 eph_gal.toc = gst2time(week, toc);
427 eph_gal.week = week + 1024; /* gal-week = gst-week + 1024 */
428 eph_gal.code = (1 << 9); /* I/NAV: af0-2,Toc,SISA for E5b-E1 */
429 eph_gal.type = 0; /* ephemeris type = I/NAV */
430 *eph = eph_gal;
431 return 1;
432}
433/* decode Galileo I/NAV iono parameters --------------------------------------*/
434static int decode_gal_inav_ion(const uint8_t* buff, double* ion) {
435 int i = 128 * 5; /* word type 5 */
436
437 trace(NULL, 4, "decode_gal_inav_ion:\n");
438
439 if (getbitu(buff, i, 6) != 5) {
440 return 0;
441 }
442 i += 6;
443 ion[0] = getbitu(buff, i, 11) * 0.25;
444 i += 11;
445 ion[1] = getbits(buff, i, 11) * P2_8;
446 i += 11;
447 ion[2] = getbits(buff, i, 14) * P2_15;
448 i += 14;
449 ion[3] = getbitu(buff, i, 5);
450 return 1;
451}
452/* decode Galileo I/NAV UTC parameters ---------------------------------------*/
453static int decode_gal_inav_utc(const uint8_t* buff, double* utc) {
454 int i = 128 * 6; /* word type 6 */
455
456 trace(NULL, 4, "decode_gal_inav_utc:\n");
457
458 if (getbitu(buff, i, 6) != 6) {
459 return 0;
460 }
461 i += 6;
462 utc[0] = getbits(buff, i, 32) * P2_30;
463 i += 32; /* A0 */
464 utc[1] = getbits(buff, i, 24) * P2_50;
465 i += 24; /* A1 */
466 utc[4] = getbits(buff, i, 8);
467 i += 8; /* dt_LS */
468 utc[2] = getbitu(buff, i, 8) * 3600.0;
469 i += 8; /* tot */
470 utc[3] = getbitu(buff, i, 8);
471 i += 8; /* WNt */
472 utc[5] = getbitu(buff, i, 8);
473 i += 8; /* WN_LSF */
474 utc[6] = getbitu(buff, i, 3);
475 i += 3; /* DN */
476 utc[7] = getbits(buff, i, 8); /* dt_LSF */
477 return 1;
478}
479/* decode Galileo I/NAV navigation data ----------------------------------------
480 * decode Galileo I/NAV navigation data (ref [5] 4.3)
481 * args : uint8_t *buff I Galileo I/NAV subframe data (CRC checked)
482 * buff[ 0- 15]: word type 0 (128 bits)
483 * buff[16- 31]: word type 1
484 * buff[32- 47]: word type 2
485 * buff[48- 63]: word type 3
486 * buff[64- 79]: word type 4
487 * buff[80- 95]: word type 5
488 * buff[96-111]: word type 6
489 * eph_t *eph IO Galileo I/NAV ephemeris (NULL: not output)
490 * double *ion IO Galileo I/NAV iono parameters (NULL: not output)
491 * ion[0-3]: a_i0,a_i1,a_i2,flags
492 * double *utc IO Galileo I/NAV UTC parameters (NULL: not output)
493 * utc[0-3]: A0,A1,tot,WNt
494 * utc[4-7]: dt_LS,WN_LSF,DN,dt_LSF
495 * return : status (1:ok,0:error)
496 *-----------------------------------------------------------------------------*/
497extern int decode_gal_inav(const uint8_t* buff, eph_t* eph, double* ion, double* utc) {
498 trace(NULL, 4, "decode_gal_fnav:\n");
499
500 if (eph && !decode_gal_inav_eph(buff, eph)) {
501 return 0;
502 }
503 if (ion && !decode_gal_inav_ion(buff, ion)) {
504 return 0;
505 }
506 if (utc && !decode_gal_inav_utc(buff, utc)) {
507 return 0;
508 }
509 return 1;
510}
511/* decode Galileo F/NAV ephemeris --------------------------------------------*/
512static int decode_gal_fnav_eph(const uint8_t* buff, eph_t* eph) {
513 eph_t eph_gal = {0};
514 double tow[4], toc, tt, sqrtA;
515 int i, week[3], svid, e5a_hs, e5a_dvs, type[4], iod_nav[4];
516
517 trace(NULL, 4, "decode_gal_fnav_eph:\n");
518
519 i = 0; /* page type 1 */
520 type[0] = getbitu(buff, i, 6);
521 i += 6;
522 svid = getbitu(buff, i, 6);
523 i += 6;
524 iod_nav[0] = getbitu(buff, i, 10);
525 i += 10;
526 toc = getbitu(buff, i, 14) * 60.0;
527 i += 14;
528 eph_gal.f0 = getbits(buff, i, 31) * P2_34;
529 i += 31;
530 eph_gal.f1 = getbits(buff, i, 21) * P2_46;
531 i += 21;
532 eph_gal.f2 = getbits(buff, i, 6) * P2_59;
533 i += 6;
534 eph_gal.sva = getbitu(buff, i, 8);
535 i += 8 + 11 + 11 + 14 + 5;
536 eph_gal.tgd[0] = getbits(buff, i, 10) * P2_32;
537 i += 10; /* BGD E5a/E1 */
538 e5a_hs = getbitu(buff, i, 2);
539 i += 2;
540 week[0] = getbitu(buff, i, 12);
541 i += 12; /* gst-week */
542 tow[0] = getbitu(buff, i, 20);
543 i += 20;
544 e5a_dvs = getbitu(buff, i, 1);
545
546 i = 31 * 8; /* page type 2 */
547 type[1] = getbitu(buff, i, 6);
548 i += 6;
549 iod_nav[1] = getbitu(buff, i, 10);
550 i += 10;
551 eph_gal.M0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
552 i += 32;
553 eph_gal.OMGd = getbits(buff, i, 24) * P2_43 * SC2RAD;
554 i += 24;
555 eph_gal.e = getbitu(buff, i, 32) * P2_33;
556 i += 32;
557 sqrtA = getbitu(buff, i, 32) * P2_19;
558 i += 32;
559 eph_gal.OMG0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
560 i += 32;
561 eph_gal.idot = getbits(buff, i, 14) * P2_43 * SC2RAD;
562 i += 14;
563 week[1] = getbitu(buff, i, 12);
564 i += 12;
565 tow[1] = getbitu(buff, i, 20);
566
567 i = 62 * 8; /* page type 3 */
568 type[2] = getbitu(buff, i, 6);
569 i += 6;
570 iod_nav[2] = getbitu(buff, i, 10);
571 i += 10;
572 eph_gal.i0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
573 i += 32;
574 eph_gal.omg = getbits(buff, i, 32) * P2_31 * SC2RAD;
575 i += 32;
576 eph_gal.deln = getbits(buff, i, 16) * P2_43 * SC2RAD;
577 i += 16;
578 eph_gal.cuc = getbits(buff, i, 16) * P2_29;
579 i += 16;
580 eph_gal.cus = getbits(buff, i, 16) * P2_29;
581 i += 16;
582 eph_gal.crc = getbits(buff, i, 16) * P2_5;
583 i += 16;
584 eph_gal.crs = getbits(buff, i, 16) * P2_5;
585 i += 16;
586 eph_gal.toes = getbitu(buff, i, 14) * 60.0;
587 i += 14;
588 week[2] = getbitu(buff, i, 12);
589 i += 12;
590 tow[2] = getbitu(buff, i, 20);
591
592 i = 93 * 8; /* page type 4 */
593 type[3] = getbitu(buff, i, 6);
594 i += 6;
595 iod_nav[3] = getbitu(buff, i, 10);
596 i += 10;
597 eph_gal.cic = getbits(buff, i, 16) * P2_29;
598 i += 16;
599 eph_gal.cis = getbits(buff, i, 16) * P2_29;
600
601 /* test page types */
602 if (type[0] != 1 || type[1] != 2 || type[2] != 3 || type[3] != 4) {
603 trace(NULL, 3, "decode_gal_fnav error: svid=%d type=%d %d %d %d\n", svid, type[0], type[1], type[2], type[3]);
604 return 0;
605 }
606 /* test consistency of iod_nav */
607 if (iod_nav[0] != iod_nav[1] || iod_nav[0] != iod_nav[2] || iod_nav[0] != iod_nav[3]) {
608 trace(NULL, 3, "decode_gal_fnav error: svid=%d iod_nav=%d %d %d %d\n", svid, iod_nav[0], iod_nav[1], iod_nav[2],
609 iod_nav[3]);
610 return 0;
611 }
612 if (!(eph_gal.sat = satno(SYS_GAL, svid))) {
613 trace(NULL, 2, "decode_gal_fnav svid error: svid=%d\n", svid);
614 return 0;
615 }
616 eph_gal.A = sqrtA * sqrtA;
617 eph_gal.tgd[1] = 0.0; /* BGD E5b/E1 */
618 eph_gal.iode = eph_gal.iodc = iod_nav[0];
619 eph_gal.svh = (e5a_hs << 4) | (e5a_dvs << 3);
620 eph_gal.ttr = gst2time(week[0], tow[0]);
621 tt = timediff(gst2time(week[0], eph_gal.toes), eph_gal.ttr);
622 if (tt > 302400.0) {
623 week[0]--; /* week consistent with toe */
624 } else if (tt < -302400.0) {
625 week[0]++;
626 }
627 eph_gal.toe = gst2time(week[0], eph_gal.toes);
628 eph_gal.toc = gst2time(week[0], toc);
629 eph_gal.week = week[0] + 1024; /* gal-week = gst-week + 1024 */
630 eph_gal.code = (1 << 8); /* F/NAV: af0-af2,Toc,SISA for E5a,E1 */
631 eph_gal.type = 1; /* ephemeris type = F/NAV */
632 *eph = eph_gal;
633 return 1;
634}
635/* decode Galileo F/NAV iono parameters --------------------------------------*/
636static int decode_gal_fnav_ion(const uint8_t* buff, double* ion) {
637 int i = 0; /* page type 1 */
638
639 trace(NULL, 4, "decode_gal_fnav_ion:\n");
640
641 if (getbitu(buff, i, 6) != 1) {
642 return 0;
643 }
644 i += 6 + 6 + 10 + 14 + 31 + 21 + 6 + 8;
645 ion[0] = getbitu(buff, i, 11) * 0.25;
646 i += 11;
647 ion[1] = getbits(buff, i, 11) * P2_8;
648 i += 11;
649 ion[2] = getbits(buff, i, 14) * P2_15;
650 i += 14;
651 ion[3] = getbitu(buff, i, 5);
652 return 1;
653}
654/* decode Galileo F/NAV UTC parameters ---------------------------------------*/
655static int decode_gal_fnav_utc(const uint8_t* buff, double* utc) {
656 int i = 93 * 8; /* page type 4 */
657
658 trace(NULL, 4, "decode_gal_fnav_utc:\n");
659
660 if (getbitu(buff, i, 6) != 4) {
661 return 0;
662 }
663 i += 6 + 10 + 16 + 16;
664 utc[0] = getbits(buff, i, 32) * P2_30;
665 i += 32; /* A0 */
666 utc[1] = getbits(buff, i, 24) * P2_50;
667 i += 24; /* A1 */
668 utc[4] = getbits(buff, i, 8);
669 i += 8; /* dt_LS */
670 utc[2] = getbitu(buff, i, 8) * 3600.0;
671 i += 8; /* tot */
672 utc[3] = getbitu(buff, i, 8);
673 i += 8; /* WN_ot */
674 utc[5] = getbitu(buff, i, 8);
675 i += 8; /* WN_LSF */
676 utc[6] = getbitu(buff, i, 3);
677 i += 3; /* DN */
678 utc[7] = getbits(buff, i, 8); /* dt_LSF */
679 return 1;
680}
681/* decode Galileo F/NAV navigation data ----------------------------------------
682 * decode Galileo F/NAV navigation data (ref [5] 4.2)
683 * args : uint8_t *buff I Galileo F/NAV subframe data (CRC checked)
684 * buff[ 0- 30]: page type 1 (244 bit)
685 * buff[ 31- 61]: page type 2
686 * buff[ 62- 92]: page type 3
687 * buff[ 93-123]: page type 4
688 * buff[124-154]: page type 5
689 * buff[155-185]: page type 6
690 * eph_t *eph IO Galileo F/NAV ephemeris (NULL: not output)
691 * double *ion IO Galileo F/NAV iono parameters (NULL: not output)
692 * ion[0-3]: a_i0,a_i1,a_i2,flags
693 * double *utc IO Galileo F/NAV UTC parameters (NULL: not output)
694 * utc[0-3]: A0,A1,tot,WNt
695 * utc[4-7]: dt_LS,WN_LSF,DN,dt_LSF
696 * return : status (1:ok,0:error)
697 *-----------------------------------------------------------------------------*/
698extern int decode_gal_fnav(const uint8_t* buff, eph_t* eph, double* ion, double* utc) {
699 trace(NULL, 4, "decode_gal_fnav:\n");
700
701 if (eph && !decode_gal_fnav_eph(buff, eph)) {
702 return 0;
703 }
704 if (ion && !decode_gal_fnav_ion(buff, ion)) {
705 return 0;
706 }
707 if (utc && !decode_gal_fnav_utc(buff, utc)) {
708 return 0;
709 }
710 return 1;
711}
712/* decode BDS D1 navigation data ---------------------------------------------*/
713static int decode_bds_d1_eph(const uint8_t* buff, eph_t* eph) {
714 eph_t eph_bds = {0};
715 double toc_bds, sqrtA;
716 uint32_t toe1, toe2, sow1, sow2, sow3;
717 int i, frn1, frn2, frn3;
718
719 i = 8 * 38 * 0; /* subframe 1 */
720 frn1 = getbitu(buff, i + 15, 3);
721 sow1 = getbitu2(buff, i + 18, 8, i + 30, 12);
722 eph_bds.svh = getbitu(buff, i + 42, 1); /* SatH1 */
723 eph_bds.iodc = getbitu(buff, i + 43, 5); /* AODC */
724 eph_bds.sva = getbitu(buff, i + 48, 4);
725 eph_bds.week = getbitu(buff, i + 60, 13); /* week in BDT */
726 toc_bds = getbitu2(buff, i + 73, 9, i + 90, 8) * 8.0;
727 eph_bds.tgd[0] = getbits(buff, i + 98, 10) * 0.1 * 1E-9;
728 eph_bds.tgd[1] = getbits2(buff, i + 108, 4, i + 120, 6) * 0.1 * 1E-9;
729 eph_bds.f2 = getbits(buff, i + 214, 11) * P2_66;
730 eph_bds.f0 = getbits2(buff, i + 225, 7, i + 240, 17) * P2_33;
731 eph_bds.f1 = getbits2(buff, i + 257, 5, i + 270, 17) * P2_50;
732 eph_bds.iode = getbitu(buff, i + 287, 5); /* AODE */
733
734 i = 8 * 38 * 1; /* subframe 2 */
735 frn2 = getbitu(buff, i + 15, 3);
736 sow2 = getbitu2(buff, i + 18, 8, i + 30, 12);
737 eph_bds.deln = getbits2(buff, i + 42, 10, i + 60, 6) * P2_43 * SC2RAD;
738 eph_bds.cuc = getbits2(buff, i + 66, 16, i + 90, 2) * P2_31;
739 eph_bds.M0 = getbits2(buff, i + 92, 20, i + 120, 12) * P2_31 * SC2RAD;
740 eph_bds.e = getbitu2(buff, i + 132, 10, i + 150, 22) * P2_33;
741 eph_bds.cus = getbits(buff, i + 180, 18) * P2_31;
742 eph_bds.crc = getbits2(buff, i + 198, 4, i + 210, 14) * P2_6;
743 eph_bds.crs = getbits2(buff, i + 224, 8, i + 240, 10) * P2_6;
744 sqrtA = getbitu2(buff, i + 250, 12, i + 270, 20) * P2_19;
745 toe1 = getbitu(buff, i + 290, 2); /* TOE 2-MSB */
746 eph_bds.A = sqrtA * sqrtA;
747
748 i = 8 * 38 * 2; /* subframe 3 */
749 frn3 = getbitu(buff, i + 15, 3);
750 sow3 = getbitu2(buff, i + 18, 8, i + 30, 12);
751 toe2 = getbitu2(buff, i + 42, 10, i + 60, 5); /* TOE 5-LSB */
752 eph_bds.i0 = getbits2(buff, i + 65, 17, i + 90, 15) * P2_31 * SC2RAD;
753 eph_bds.cic = getbits2(buff, i + 105, 7, i + 120, 11) * P2_31;
754 eph_bds.OMGd = getbits2(buff, i + 131, 11, i + 150, 13) * P2_43 * SC2RAD;
755 eph_bds.cis = getbits2(buff, i + 163, 9, i + 180, 9) * P2_31;
756 eph_bds.idot = getbits2(buff, i + 189, 13, i + 210, 1) * P2_43 * SC2RAD;
757 eph_bds.OMG0 = getbits2(buff, i + 211, 21, i + 240, 11) * P2_31 * SC2RAD;
758 eph_bds.omg = getbits2(buff, i + 251, 11, i + 270, 21) * P2_31 * SC2RAD;
759 eph_bds.toes = merge_two_u(toe1, toe2, 15) * 8.0;
760
761 /* check consistency of subframe ids, sows and toe/toc */
762 if (frn1 != 1 || frn2 != 2 || frn3 != 3) {
763 trace(NULL, 3, "decode_bds_d1_eph error: frn=%d %d %d\n", frn1, frn2, frn3);
764 return 0;
765 }
766 if (sow2 != sow1 + 6 || sow3 != sow2 + 6) {
767 trace(NULL, 3, "decode_bds_d1_eph error: sow=%d %d %d\n", sow1, sow2, sow3);
768 return 0;
769 }
770 if (toc_bds != eph_bds.toes) {
771 trace(NULL, 3, "decode_bds_d1_eph error: toe=%.0f toc=%.0f\n", eph_bds.toes, toc_bds);
772 return 0;
773 }
774 eph_bds.ttr = bdt2gpst(bdt2time(eph_bds.week, sow1)); /* bdt -> gpst */
775 if (eph_bds.toes > sow1 + 302400.0) {
776 eph_bds.week++;
777 } else if (eph_bds.toes < sow1 - 302400.0) {
778 eph_bds.week--;
779 }
780 eph_bds.toe = bdt2gpst(bdt2time(eph_bds.week, eph_bds.toes));
781 eph_bds.toc = bdt2gpst(bdt2time(eph_bds.week, toc_bds));
782 eph_bds.code = 0; /* data source = unknown */
783 eph_bds.flag = 1; /* nav type = IGSO/MEO */
784 eph_bds.type = 0; /* ephemeris type = D1 */
785 *eph = eph_bds;
786 return 1;
787}
788/* decode BDS D1 iono parameters ---------------------------------------------*/
789static int decode_bds_d1_ion(const uint8_t* buff, double* ion) {
790 int i = 8 * 38 * 0; /* subframe 1 */
791
792 trace(NULL, 4, "decode_bds_d1_ion:\n");
793
794 /* subframe 1 */
795 if (getbitu(buff, i + 15, 3) != 1) {
796 return 0;
797 }
798
799 ion[0] = getbits(buff, i + 126, 8) * P2_30;
800 ion[1] = getbits(buff, i + 134, 8) * P2_27;
801 ion[2] = getbits(buff, i + 150, 8) * P2_24;
802 ion[3] = getbits(buff, i + 158, 8) * P2_24;
803 ion[4] = getbits2(buff, i + 166, 6, i + 180, 2) * P2P11;
804 ion[5] = getbits(buff, i + 182, 8) * P2P14;
805 ion[6] = getbits(buff, i + 190, 8) * P2P16;
806 ion[7] = getbits2(buff, i + 198, 4, i + 210, 4) * P2P16;
807 return 1;
808}
809/* decode BDS D1 UTC parameters ----------------------------------------------*/
810static int decode_bds_d1_utc(const uint8_t* buff, double* utc) {
811 int i = 8 * 38 * 4; /* subframe 5 */
812
813 trace(NULL, 4, "decode_bds_d1_utc:\n");
814
815 if (getbitu(buff, 15, 3) != 1) {
816 return 0; /* subframe 1 */
817 }
818
819 /* subframe 5 page 10 */
820 if (getbitu(buff, i + 15, 3) != 5 || getbitu(buff, i + 43, 7) != 10) {
821 return 0;
822 }
823
824 utc[4] = getbits2(buff, i + 50, 2, i + 60, 6); /* dt_LS */
825 utc[7] = getbits(buff, i + 66, 8); /* dt_LSF */
826 utc[5] = getbitu(buff, i + 74, 8); /* WN_LSF */
827 utc[0] = getbits2(buff, i + 90, 22, i + 120, 10) * P2_30; /* A0 */
828 utc[1] = getbits2(buff, i + 130, 12, i + 150, 12) * P2_50; /* A1 */
829 utc[6] = getbitu(buff, i + 162, 8); /* DN */
830 utc[2] = getbitu2(buff, i + 18, 8, i + 30, 12); /* SOW */
831 utc[3] = getbitu(buff, 60, 13); /* WN */
832 return 1;
833}
834/* decode BDS D1 navigation data -----------------------------------------------
835 * decode BDS D1 navigation data (IGSO/MEO) (ref [3] 5.2)
836 * args : uint8_t *buff I BDS D1 subframe data (CRC checked with parity)
837 * buff[ 0- 37]: subframe 1 (300 bits)
838 * buff[ 38- 75]: subframe 2
839 * buff[ 76-113]: subframe 3
840 * buff[114-141]: subframe 4
841 * buff[152-189]: subframe 5
842 * eph_t *eph IO BDS D1 ephemeris (NULL: not output)
843 * double *ion IO BDS D1 iono parameters (NULL: not output)
844 * ion[0-3]: alpha_0,...,alpha_3
845 * ion[4-7]: beta_0,...,beta_3
846 * double *utc IO BDS D1 UTC parameters (NULL: not output)
847 * utc[0-2]: A0,A1,tot,WNt
848 * utc[4-7]: dt_LS,WN_LSF,DN,dt_LSF
849 * return : status (1:ok,0:error)
850 *-----------------------------------------------------------------------------*/
851extern int decode_bds_d1(const uint8_t* buff, eph_t* eph, double* ion, double* utc) {
852 trace(NULL, 4, "decode_bds_d1:\n");
853
854 if (eph && !decode_bds_d1_eph(buff, eph)) {
855 return 0;
856 }
857 if (ion && !decode_bds_d1_ion(buff, ion)) {
858 return 0;
859 }
860 if (utc && !decode_bds_d1_utc(buff, utc)) {
861 return 0;
862 }
863 return 1;
864}
865/* decode BDS D2 ephemeris ---------------------------------------------------*/
866static int decode_bds_d2_eph(const uint8_t* buff, eph_t* eph) {
867 eph_t eph_bds = {0};
868 double toc_bds, sqrtA;
869 uint32_t f1p4, cucp5, ep6, cicp7, i0p8, OMGdp9, omgp10;
870 uint32_t sow1, sow3, sow4, sow5, sow6, sow7, sow8, sow9, sow10;
871 int i, f1p3, cucp4, ep5, cicp6, i0p7, OMGdp8, omgp9;
872 int pgn1, pgn3, pgn4, pgn5, pgn6, pgn7, pgn8, pgn9, pgn10;
873
874 trace(NULL, 4, "decode_bds_d1_eph:\n");
875
876 i = 8 * 38 * 0; /* page 1 */
877 pgn1 = getbitu(buff, i + 42, 4);
878 sow1 = getbitu2(buff, i + 18, 8, i + 30, 12);
879 eph_bds.svh = getbitu(buff, i + 46, 1); /* SatH1 */
880 eph_bds.iodc = getbitu(buff, i + 47, 5); /* AODC */
881 eph_bds.sva = getbitu(buff, i + 60, 4);
882 eph_bds.week = getbitu(buff, i + 64, 13); /* week in BDT */
883 toc_bds = getbitu2(buff, i + 77, 5, i + 90, 12) * 8.0;
884 eph_bds.tgd[0] = getbits(buff, i + 102, 10) * 0.1 * 1E-9;
885 eph_bds.tgd[1] = getbits(buff, i + 120, 10) * 0.1 * 1E-9;
886
887 i = 8 * 38 * 2; /* page 3 */
888 pgn3 = getbitu(buff, i + 42, 4);
889 sow3 = getbitu2(buff, i + 18, 8, i + 30, 12);
890 eph_bds.f0 = getbits2(buff, i + 100, 12, i + 120, 12) * P2_33;
891 f1p3 = getbits(buff, i + 132, 4);
892
893 i = 8 * 38 * 3; /* page 4 */
894 pgn4 = getbitu(buff, i + 42, 4);
895 sow4 = getbitu2(buff, i + 18, 8, i + 30, 12);
896 f1p4 = getbitu2(buff, i + 46, 6, i + 60, 12);
897 eph_bds.f2 = getbits2(buff, i + 72, 10, i + 90, 1) * P2_66;
898 eph_bds.iode = getbitu(buff, i + 91, 5); /* AODE */
899 eph_bds.deln = getbits(buff, i + 96, 16) * P2_43 * SC2RAD;
900 cucp4 = getbits(buff, i + 120, 14);
901
902 i = 8 * 38 * 4; /* page 5 */
903 pgn5 = getbitu(buff, i + 42, 4);
904 sow5 = getbitu2(buff, i + 18, 8, i + 30, 12);
905 cucp5 = getbitu(buff, i + 46, 4);
906 eph_bds.M0 = getbits3(buff, i + 50, 2, i + 60, 22, i + 90, 8) * P2_31 * SC2RAD;
907 eph_bds.cus = getbits2(buff, i + 98, 14, i + 120, 4) * P2_31;
908 ep5 = getbits(buff, i + 124, 10);
909
910 i = 8 * 38 * 5; /* page 6 */
911 pgn6 = getbitu(buff, i + 42, 4);
912 sow6 = getbitu2(buff, i + 18, 8, i + 30, 12);
913 ep6 = getbitu2(buff, i + 46, 6, i + 60, 16);
914 sqrtA = getbitu3(buff, i + 76, 6, i + 90, 22, i + 120, 4) * P2_19;
915 cicp6 = getbits(buff, i + 124, 10);
916 eph_bds.A = sqrtA * sqrtA;
917
918 i = 8 * 38 * 6; /* page 7 */
919 pgn7 = getbitu(buff, i + 42, 4);
920 sow7 = getbitu2(buff, i + 18, 8, i + 30, 12);
921 cicp7 = getbitu2(buff, i + 46, 6, i + 60, 2);
922 eph_bds.cis = getbits(buff, i + 62, 18) * P2_31;
923 eph_bds.toes = getbitu2(buff, i + 80, 2, i + 90, 15) * 8.0;
924 i0p7 = getbits2(buff, i + 105, 7, i + 120, 14);
925
926 i = 8 * 38 * 7; /* page 8 */
927 pgn8 = getbitu(buff, i + 42, 4);
928 sow8 = getbitu2(buff, i + 18, 8, i + 30, 12);
929 i0p8 = getbitu2(buff, i + 46, 6, i + 60, 5);
930 eph_bds.crc = getbits2(buff, i + 65, 17, i + 90, 1) * P2_6;
931 eph_bds.crs = getbits(buff, i + 91, 18) * P2_6;
932 OMGdp8 = getbits2(buff, i + 109, 3, i + 120, 16);
933
934 i = 8 * 38 * 8; /* page 9 */
935 pgn9 = getbitu(buff, i + 42, 4);
936 sow9 = getbitu2(buff, i + 18, 8, i + 30, 12);
937 OMGdp9 = getbitu(buff, i + 46, 5);
938 eph_bds.OMG0 = getbits3(buff, i + 51, 1, i + 60, 22, i + 90, 9) * P2_31 * SC2RAD;
939 omgp9 = getbits2(buff, i + 99, 13, i + 120, 14);
940
941 i = 8 * 38 * 9; /* page 10 */
942 pgn10 = getbitu(buff, i + 42, 4);
943 sow10 = getbitu2(buff, i + 18, 8, i + 30, 12);
944 omgp10 = getbitu(buff, i + 46, 5);
945 eph_bds.idot = getbits2(buff, i + 51, 1, i + 60, 13) * P2_43 * SC2RAD;
946
947 /* check consistency of page numbers, sows and toe/toc */
948 if (pgn1 != 1 || pgn3 != 3 || pgn4 != 4 || pgn5 != 5 || pgn6 != 6 || pgn7 != 7 || pgn8 != 8 || pgn9 != 9 ||
949 pgn10 != 10) {
950 trace(NULL, 3, "decode_bds_d2 error: pgn=%d %d %d %d %d %d %d %d %d\n", pgn1, pgn3, pgn4, pgn5, pgn6, pgn7,
951 pgn8, pgn9, pgn10);
952 return 0;
953 }
954 if (sow3 != sow1 + 6 || sow4 != sow3 + 3 || sow5 != sow4 + 3 || sow6 != sow5 + 3 || sow7 != sow6 + 3 ||
955 sow8 != sow7 + 3 || sow9 != sow8 + 3 || sow10 != sow9 + 3) {
956 trace(NULL, 3, "decode_bds_d2 error: sow=%d %d %d %d %d %d %d %d %d\n", sow1, sow3, sow4, sow5, sow6, sow7,
957 sow8, sow9, sow10);
958 return 0;
959 }
960 if (toc_bds != eph_bds.toes) {
961 trace(NULL, 3, "decode_bds_d2 error: toe=%.0f toc=%.0f\n", eph_bds.toes, toc_bds);
962 return 0;
963 }
964 eph_bds.f1 = merge_two_s(f1p3, f1p4, 18) * P2_50;
965 eph_bds.cuc = merge_two_s(cucp4, cucp5, 4) * P2_31;
966 eph_bds.e = merge_two_s(ep5, ep6, 22) * P2_33;
967 eph_bds.cic = merge_two_s(cicp6, cicp7, 8) * P2_31;
968 eph_bds.i0 = merge_two_s(i0p7, i0p8, 11) * P2_31 * SC2RAD;
969 eph_bds.OMGd = merge_two_s(OMGdp8, OMGdp9, 5) * P2_43 * SC2RAD;
970 eph_bds.omg = merge_two_s(omgp9, omgp10, 5) * P2_31 * SC2RAD;
971
972 eph_bds.ttr = bdt2gpst(bdt2time(eph_bds.week, sow1)); /* bdt -> gpst */
973 if (eph_bds.toes > sow1 + 302400.0) {
974 eph_bds.week++;
975 } else if (eph_bds.toes < sow1 - 302400.0) {
976 eph_bds.week--;
977 }
978 eph_bds.toe = bdt2gpst(bdt2time(eph_bds.week, eph_bds.toes));
979 eph_bds.toc = bdt2gpst(bdt2time(eph_bds.week, toc_bds));
980 eph_bds.code = 0; /* data source = unknown */
981 eph_bds.flag = 2; /* nav type = GEO */
982 eph_bds.type = 1; /* ephemeris type = D2 */
983 *eph = eph_bds;
984 return 1;
985}
986/* decode BDS D2 UTC parameters ----------------------------------------------*/
987static int decode_bds_d2_utc(const uint8_t* buff, double* utc) {
988 int i = 8 * 38 * 10; /* subframe 5 pase 102 */
989
990 trace(NULL, 4, "decode_bds_d2_utc:\n");
991
992 /* subframe 1 page 1 */
993 if (getbitu(buff, 15, 3) != 1 || getbitu(buff, 42, 4) != 1) {
994 return 0;
995 }
996
997 /* subframe 5 page 102 */
998 if (getbitu(buff, i + 15, 3) != 5 || getbitu(buff, i + 43, 7) != 102) {
999 return 0;
1000 }
1001
1002 utc[4] = getbits2(buff, i + 50, 2, i + 60, 6); /* dt_LS */
1003 utc[7] = getbits(buff, i + 66, 8); /* dt_LSF */
1004 utc[5] = getbitu(buff, i + 74, 8); /* WN_LSF */
1005 utc[0] = getbits2(buff, i + 90, 22, i + 120, 10) * P2_30; /* A0 */
1006 utc[1] = getbits2(buff, i + 130, 12, i + 150, 12) * P2_50; /* A1 */
1007 utc[6] = getbitu(buff, i + 162, 8); /* DN */
1008 utc[2] = getbits2(buff, i + 18, 8, i + 30, 12); /* SOW */
1009 utc[3] = getbitu(buff, 64, 13); /* WN */
1010 return 1;
1011}
1012/* decode BDS D2 navigation data -----------------------------------------------
1013 * decode BDS D2 navigation data (GEO) (ref [3] 5.3)
1014 * args : uint8_t *buff I BDS D2 subframe data (CRC checked with parity)
1015 * buff[ 0- 37]: subframe 1 page 1 (300 bits)
1016 * buff[ 38- 75]: subframe 1 page 2
1017 * ...
1018 * buff[342-379]: subframe 1 page 10
1019 * buff[380-417]: subframe 5 page 102
1020 * eph_t *eph IO BDS D2 ephemeris (NULL: not output)
1021 * double *utc IO BDS D2 UTC parameters (NULL: not output)
1022 * utc[0-2]: A0,A1,tot,WNt
1023 * utc[4-7]: dt_LS,WN_LSF,DN,dt_LSF
1024 * return : status (1:ok,0:error)
1025 *-----------------------------------------------------------------------------*/
1026extern int decode_bds_d2(const uint8_t* buff, eph_t* eph, double* utc) {
1027 trace(NULL, 4, "decode_bds_d2:\n");
1028
1029 if (eph && !decode_bds_d2_eph(buff, eph)) {
1030 return 0;
1031 }
1032 if (utc && !decode_bds_d2_utc(buff, utc)) {
1033 return 0;
1034 }
1035 return 1;
1036}
1037/* test hamming code of GLONASS navigation string ------------------------------
1038 * test hamming code of GLONASS navigation string (ref [2] 4.7)
1039 * args : uint8_t *buff I GLONASS navigation string with hamming code
1040 * buff[ 0]: string bit 85-78
1041 * buff[ 1]: string bit 77-70
1042 * ...
1043 * buff[10]: string bit 5- 1 (0 padded)
1044 * return : status (1:ok,0:error)
1045 *-----------------------------------------------------------------------------*/
1046extern int test_glostr(const uint8_t* buff) {
1047 static const uint8_t xor_8bit[256] = {
1048 /* xor of 8 bits */
1049 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0,
1050 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1,
1051 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1,
1052 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0,
1053 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0,
1054 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0,
1055 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
1056 static const uint8_t mask_hamming[][12] = {/* mask of hamming codes */
1057 {0x55, 0x55, 0x5A, 0xAA, 0xAA, 0xAA, 0xB5, 0x55, 0x6A, 0xD8, 0x08},
1058 {0x66, 0x66, 0x6C, 0xCC, 0xCC, 0xCC, 0xD9, 0x99, 0xB3, 0x68, 0x10},
1059 {0x87, 0x87, 0x8F, 0x0F, 0x0F, 0x0F, 0x1E, 0x1E, 0x3C, 0x70, 0x20},
1060 {0x07, 0xF8, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0x80, 0x40},
1061 {0xF8, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x80},
1062 {0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0x00},
1063 {0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
1064 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8}};
1065 uint8_t cs;
1066 int i, j, n = 0;
1067
1068 for (i = 0; i < 8; i++) {
1069 for (j = 0, cs = 0; j < 11; j++) {
1070 cs ^= xor_8bit[buff[j] & mask_hamming[i][j]];
1071 }
1072 if (cs) {
1073 n++;
1074 }
1075 }
1076 return n == 0 || (n == 2 && cs);
1077}
1078#if 0
1079/* decode GLONASS almanac ----------------------------------------------------*/
1080static int decode_glostr_alm(const uint8_t *buff, galm_t *galm)
1081{
1082 galm_t galm_glo={0};
1083 gtime_t t_glo;
1084 double ep[6]={1996,1,1};
1085 int i,j,frn1,frn2,frn3,frn4,P3,N4,NA,slot,sat,ret=0;
1086
1087 i=1+80*2; /* string 3 */
1088 frn1=getbitu(buff,i, 4); i+=4;
1089 P3 =getbitu(buff,i, 1);
1090
1091 i=1+80*4; /* string 5 */
1092 frn2=getbitu(buff,i, 4); i+= 4;
1093 NA =getbitu(buff,i,11); i+=11+32+1;
1094 N4 =getbitu(buff,i, 5);
1095
1096 if (frn1!=3||frn2!=5) return 0;
1097
1098 for (j=0;j<(P3?5:4);j++) {
1099 i=1+80*(5+j*2); /* string 6,8,10,12,14 */
1100 frn3 =getbitu(buff,i, 4); i+= 4;
1101 galm_glo.Cn =getbitu(buff,i, 1); i+= 1;
1102 galm_glo.Mn =getbitu(buff,i, 2); i+= 2;
1103 slot =getbitu(buff,i, 5); i+= 5;
1104 galm_glo.taun=getbits(buff,i,10)*P2_18; i+=10;
1105 galm_glo.lamn=getbits(buff,i,21)*P2_20; i+=21;
1106 galm_glo.din =getbits(buff,i,18)*P2_20*SC2RAD; i+=18;
1107 galm_glo.eccn=getbitu(buff,i,15)*P2_20;
1108
1109 i=1+80*(6+j*2); /* string 7,9,11,13,15 */
1110 frn4 =getbitu(buff,i, 4); i+= 4;
1111 galm_glo.omgn=getbitu(buff,i,16)*P2_15*SC2RAD; i+=16;
1112 galm_glo.tn =getbitu(buff,i,21)*P2_5; i+=21;
1113 galm_glo.dTn =getbits(buff,i,22)*P2_9; i+=22;
1114 galm_glo.ddTn=getbits(buff,i, 7)*P2_14; i+= 7;
1115 galm_glo.Hn =getbitu(buff,i, 5);
1116
1117 if (frn3!=6+j*2||frn4!=7+j*2||!(sat=satno(SYS_GLO,slot))) continue;
1118
1119 galm_glo.sat=sat;
1120 ep[0]=1996+(N4-1)*4;
1121 t_glo=timeadd(epoch2time(ep),86400.0*(NA-1)+10800.0); /* UTC+3H */
1122 galm_glo.toa=timeadd(t_glo,galm_glo.tn); /* in UTC */
1123 galm[slot-1]=galm_glo;
1124 ret=1;
1125 }
1126 return ret;
1127}
1128#endif
1129/* decode GLONASS ephemeris --------------------------------------------------*/
1130static int decode_glostr_eph(const uint8_t* buff, geph_t* geph) {
1131 geph_t geph_glo = {0};
1132 double tow, tod, tof, toe;
1133 int P, P1, P2, P3, P4, tk_h, tk_m, tk_s, tb, Bn, ln, NT, slot, M, week;
1134 int i = 1, frn1, frn2, frn3, frn4;
1135
1136 trace(NULL, 4, "decode_glostr_eph:\n");
1137
1138 /* string 1 */
1139 frn1 = getbitu(buff, i, 4);
1140 i += 4 + 2;
1141 P1 = getbitu(buff, i, 2);
1142 i += 2;
1143 tk_h = getbitu(buff, i, 5);
1144 i += 5;
1145 tk_m = getbitu(buff, i, 6);
1146 i += 6;
1147 tk_s = getbitu(buff, i, 1) * 30;
1148 i += 1;
1149 geph_glo.vel[0] = getbitg(buff, i, 24) * P2_20 * 1E3;
1150 i += 24;
1151 geph_glo.acc[0] = getbitg(buff, i, 5) * P2_30 * 1E3;
1152 i += 5;
1153 geph_glo.pos[0] = getbitg(buff, i, 27) * P2_11 * 1E3;
1154 i += 27 + 4;
1155
1156 /* string 2 */
1157 frn2 = getbitu(buff, i, 4);
1158 i += 4;
1159 Bn = getbitu(buff, i, 1);
1160 i += 1 + 2; /* MSB of Bn */
1161 P2 = getbitu(buff, i, 1);
1162 i += 1;
1163 tb = getbitu(buff, i, 7);
1164 i += 7 + 5;
1165 geph_glo.vel[1] = getbitg(buff, i, 24) * P2_20 * 1E3;
1166 i += 24;
1167 geph_glo.acc[1] = getbitg(buff, i, 5) * P2_30 * 1E3;
1168 i += 5;
1169 geph_glo.pos[1] = getbitg(buff, i, 27) * P2_11 * 1E3;
1170 i += 27 + 4;
1171
1172 /* string 3 */
1173 frn3 = getbitu(buff, i, 4);
1174 i += 4;
1175 P3 = getbitu(buff, i, 1);
1176 i += 1;
1177 geph_glo.gamn = getbitg(buff, i, 11) * P2_40;
1178 i += 11 + 1;
1179 P = getbitu(buff, i, 2);
1180 i += 2;
1181 ln = getbitu(buff, i, 1);
1182 i += 1;
1183 geph_glo.vel[2] = getbitg(buff, i, 24) * P2_20 * 1E3;
1184 i += 24;
1185 geph_glo.acc[2] = getbitg(buff, i, 5) * P2_30 * 1E3;
1186 i += 5;
1187 geph_glo.pos[2] = getbitg(buff, i, 27) * P2_11 * 1E3;
1188 i += 27 + 4;
1189
1190 /* string 4 */
1191 frn4 = getbitu(buff, i, 4);
1192 i += 4;
1193 geph_glo.taun = getbitg(buff, i, 22) * P2_30;
1194 i += 22;
1195 geph_glo.dtaun = getbitg(buff, i, 5) * P2_30;
1196 i += 5;
1197 geph_glo.age = getbitu(buff, i, 5);
1198 i += 5 + 14; /* E_n */
1199 P4 = getbitu(buff, i, 1);
1200 i += 1;
1201 geph_glo.sva = getbitu(buff, i, 4);
1202 i += 4 + 3; /* F_T */
1203 NT = getbitu(buff, i, 11);
1204 i += 11;
1205 slot = getbitu(buff, i, 5);
1206 i += 5;
1207 M = getbitu(buff, i, 2);
1208
1209 if (frn1 != 1 || frn2 != 2 || frn3 != 3 || frn4 != 4) {
1210 trace(NULL, 3, "decode_glostr error: frn=%d %d %d %d %d\n", frn1, frn2, frn3, frn4);
1211 return 0;
1212 }
1213 if (!(geph_glo.sat = satno(SYS_GLO, slot))) {
1214 trace(NULL, 2, "decode_glostr error: slot=%d\n", slot);
1215 return 0;
1216 }
1217 geph_glo.frq = 0; /* set default */
1218 geph_glo.iode = tb;
1219 geph_glo.svh = (ln << 3) + Bn; /* extended SVH */
1220 geph_glo.flags = (M << 7) + (P4 << 6) + (P3 << 5) + (P2 << 4) + (P1 << 2) + P; /* status flags */
1221 tow = time2gpst(gpst2utc(geph->tof), &week);
1222 tod = fmod(tow, 86400.0);
1223 tow -= tod;
1224 tof = tk_h * 3600.0 + tk_m * 60.0 + tk_s - 10800.0; /* lt->utc */
1225 if (tof < tod - 43200.0) {
1226 tof += 86400.0;
1227 } else if (tof > tod + 43200.0) {
1228 tof -= 86400.0;
1229 }
1230 geph_glo.tof = utc2gpst(gpst2time(week, tow + tof));
1231 toe = tb * 900.0 - 10800.0; /* lt->utc */
1232 if (toe < tod - 43200.0) {
1233 toe += 86400.0;
1234 } else if (toe > tod + 43200.0) {
1235 toe -= 86400.0;
1236 }
1237 geph_glo.toe = utc2gpst(gpst2time(week, tow + toe)); /* utc->gpst */
1238 *geph = geph_glo;
1239 return 1;
1240}
1241/* decode GLONASS UTC parameters ---------------------------------------------*/
1242static int decode_glostr_utc(const uint8_t* buff, double* utc) {
1243 int i = 1 + 80 * 4; /* string 5 */
1244
1245 trace(NULL, 4, "decode_glostr_utc:\n");
1246
1247 /* string 5 */
1248 if (getbitu(buff, i, 4) != 5) {
1249 return 0;
1250 }
1251 i += 4 + 11;
1252 utc[0] = getbits(buff, i, 32) * P2_31;
1253 i += 32 + 1 + 6; /* tau_C */
1254 utc[1] = getbits(buff, i, 22) * P2_30; /* tau_GPS */
1255 utc[2] = utc[3] = utc[4] = utc[5] = utc[6] = utc[7] = 0.0;
1256 return 1;
1257}
1258/* decode GLONASS navigation data strings --------------------------------------
1259 * decode GLONASS navigation data string (ref [2])
1260 * args : uint8_t *buff I GLONASS navigation data string
1261 * (w/o hamming and time mark)
1262 * buff[ 0- 9]: string 1 (77 bits)
1263 * buff[ 10- 19]: string 2
1264 * buff[ 20- 29]: string 3
1265 * buff[ 30- 39]: string 4
1266 * buff[ 40- 49]: string 5
1267 * ...
1268 * buff[140-149]: string 15
1269 * geph_t *geph IO GLONASS ephemeris (NULL: not output)
1270 * geph[slot-1]: satellite with slot ephemeris
1271 * double *utc IO GLONASS UTC parameters (NULL: not output)
1272 * utc[0] : A0 (=-tau_C)
1273 * utc[1-7]: reserved
1274 * return : status (1:ok,0:error)
1275 * notes : geph->tof should be set to frame time within 1/2 day before calling
1276 * geph->frq is set to 0
1277 *-----------------------------------------------------------------------------*/
1278extern int decode_glostr(const uint8_t* buff, geph_t* geph, double* utc) {
1279 trace(NULL, 4, "decode_glostr:\n");
1280
1281 if (geph && !decode_glostr_eph(buff, geph)) {
1282 return 0;
1283 }
1284 if (utc && !decode_glostr_utc(buff, utc)) {
1285 return 0;
1286 }
1287 return 1;
1288}
1289/* decode GPS/QZSS ephemeris -------------------------------------------------*/
1290static int decode_frame_eph(const uint8_t* buff, eph_t* eph) {
1291 eph_t eph_sat = {0};
1292 double tow1, tow2, tow3, toc, sqrtA;
1293 int i = 48, id1, id2, id3, week, iodc0, iodc1, iode, tgd;
1294
1295 trace(NULL, 4, "decode_frame_eph:\n");
1296
1297 i = 240 * 0 + 24; /* subframe 1 */
1298 tow1 = getbitu(buff, i, 17) * 6.0;
1299 i += 17 + 2;
1300 id1 = getbitu(buff, i, 3);
1301 i += 3 + 2;
1302 week = getbitu(buff, i, 10);
1303 i += 10;
1304 eph_sat.code = getbitu(buff, i, 2);
1305 i += 2;
1306 eph_sat.sva = getbitu(buff, i, 4);
1307 i += 4; /* ura index */
1308 eph_sat.svh = getbitu(buff, i, 6);
1309 i += 6;
1310 iodc0 = getbitu(buff, i, 2);
1311 i += 2;
1312 eph_sat.flag = getbitu(buff, i, 1);
1313 i += 1 + 87;
1314 tgd = getbits(buff, i, 8);
1315 i += 8;
1316 iodc1 = getbitu(buff, i, 8);
1317 i += 8;
1318 toc = getbitu(buff, i, 16) * 16.0;
1319 i += 16;
1320 eph_sat.f2 = getbits(buff, i, 8) * P2_55;
1321 i += 8;
1322 eph_sat.f1 = getbits(buff, i, 16) * P2_43;
1323 i += 16;
1324 eph_sat.f0 = getbits(buff, i, 22) * P2_31;
1325
1326 i = 240 * 1 + 24; /* subframe 2 */
1327 tow2 = getbitu(buff, i, 17) * 6.0;
1328 i += 17 + 2;
1329 id2 = getbitu(buff, i, 3);
1330 i += 3 + 2;
1331 eph_sat.iode = getbitu(buff, i, 8);
1332 i += 8;
1333 eph_sat.crs = getbits(buff, i, 16) * P2_5;
1334 i += 16;
1335 eph_sat.deln = getbits(buff, i, 16) * P2_43 * SC2RAD;
1336 i += 16;
1337 eph_sat.M0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
1338 i += 32;
1339 eph_sat.cuc = getbits(buff, i, 16) * P2_29;
1340 i += 16;
1341 eph_sat.e = getbitu(buff, i, 32) * P2_33;
1342 i += 32;
1343 eph_sat.cus = getbits(buff, i, 16) * P2_29;
1344 i += 16;
1345 sqrtA = getbitu(buff, i, 32) * P2_19;
1346 i += 32;
1347 eph_sat.toes = getbitu(buff, i, 16) * 16.0;
1348 i += 16;
1349 eph_sat.fit = getbitu(buff, i, 1) ? 0.0 : 4.0; /* 0:4hr,1:>4hr */
1350
1351 i = 240 * 2 + 24; /* subframe 3 */
1352 tow3 = getbitu(buff, i, 17) * 6.0;
1353 i += 17 + 2;
1354 id3 = getbitu(buff, i, 3);
1355 i += 3 + 2;
1356 eph_sat.cic = getbits(buff, i, 16) * P2_29;
1357 i += 16;
1358 eph_sat.OMG0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
1359 i += 32;
1360 eph_sat.cis = getbits(buff, i, 16) * P2_29;
1361 i += 16;
1362 eph_sat.i0 = getbits(buff, i, 32) * P2_31 * SC2RAD;
1363 i += 32;
1364 eph_sat.crc = getbits(buff, i, 16) * P2_5;
1365 i += 16;
1366 eph_sat.omg = getbits(buff, i, 32) * P2_31 * SC2RAD;
1367 i += 32;
1368 eph_sat.OMGd = getbits(buff, i, 24) * P2_43 * SC2RAD;
1369 i += 24;
1370 iode = getbitu(buff, i, 8);
1371 i += 8;
1372 eph_sat.idot = getbits(buff, i, 14) * P2_43 * SC2RAD;
1373
1374 eph_sat.A = sqrtA * sqrtA;
1375 eph_sat.iodc = (iodc0 << 8) + iodc1;
1376 eph_sat.tgd[0] = (tgd == -128) ? 0.0 : tgd * P2_31; /* ref [4] */
1377
1378 /* test subframe ids */
1379 if (id1 != 1 || id2 != 2 || id3 != 3) {
1380 trace(NULL, 3, "decode_frame_eph error: id=%d %d %d\n", id1, id2, id3);
1381 return 0;
1382 }
1383 /* test iode and iodc consistency */
1384 if (iode != eph_sat.iode || iode != (eph_sat.iodc & 0xFF)) {
1385 trace(NULL, 3, "decode_frame_eph error: iode=%d %d iodc=%d\n", eph_sat.iode, iode, eph_sat.iodc);
1386 return 0;
1387 }
1388 eph_sat.week = adjgpsweek(week);
1389 eph_sat.ttr = gpst2time(eph_sat.week, tow1);
1390 if (eph_sat.toes < tow1 - 302400.0) {
1391 eph_sat.week++;
1392 } else if (eph_sat.toes > tow1 + 302400.0) {
1393 eph_sat.week--;
1394 }
1395 eph_sat.toe = gpst2time(eph_sat.week, eph_sat.toes);
1396 eph_sat.toc = gpst2time(eph_sat.week, toc);
1397 eph_sat.type = 0; /* ephemeris type = LNAV */
1398 *eph = eph_sat;
1399 return 1;
1400}
1401/* decode GPS/QZSS satellite almanac -----------------------------------------*/
1402static void decode_alm_sat(const uint8_t* buff, int type, alm_t* alm) {
1403 gtime_t toa0 = {0};
1404 double deltai, sqrtA, i_ref, e_ref;
1405 int i = 50, f0;
1406
1407 trace(NULL, 4, "decode_alm_sat:\n");
1408
1409 /* type=0:GPS,1:QZS-QZO,2:QZS-GEO */
1410 if (type == 0) {
1411 e_ref = 0.0;
1412 } else if (type == 1) {
1413 e_ref = 0.06;
1414 } else {
1415 e_ref = 0.0;
1416 }
1417 if (type == 0) {
1418 i_ref = 0.3;
1419 } else if (type == 1) {
1420 i_ref = 0.25;
1421 } else {
1422 i_ref = 0.0;
1423 }
1424
1425 alm->e = getbits(buff, i, 16) * P2_21 + e_ref;
1426 i += 16;
1427 alm->toas = getbitu(buff, i, 8) * 4096.0;
1428 i += 8;
1429 deltai = getbits(buff, i, 16) * P2_19;
1430 i += 16;
1431 alm->OMGd = getbits(buff, i, 16) * P2_38 * SC2RAD;
1432 i += 16;
1433 alm->svh = getbitu(buff, i, 8);
1434 i += 8;
1435 sqrtA = getbitu(buff, i, 24) * P2_11;
1436 i += 24;
1437 alm->OMG0 = getbits(buff, i, 24) * P2_23 * SC2RAD;
1438 i += 24;
1439 alm->omg = getbits(buff, i, 24) * P2_23 * SC2RAD;
1440 i += 24;
1441 alm->M0 = getbits(buff, i, 24) * P2_23 * SC2RAD;
1442 i += 24;
1443 f0 = getbits(buff, i, 8);
1444 i += 8;
1445 alm->f1 = getbits(buff, i, 11) * P2_38;
1446 i += 11;
1447 alm->f0 = getbitu(buff, i, 3) * P2_17 + f0 * P2_20;
1448 alm->A = sqrtA * sqrtA;
1449 alm->i0 = (i_ref + deltai) * SC2RAD;
1450 alm->week = 0;
1451 alm->toa = toa0;
1452}
1453/* decode GPS almanac/health -------------------------------------------------*/
1454static int decode_alm_gps(const uint8_t* buff, int frm, alm_t* alm) {
1455 int i, j, sat, toas, week, svid = getbitu(buff, 50, 6);
1456
1457 trace(NULL, 4, "decode_alm_gps:\n");
1458
1459 if ((frm == 5 && svid >= 1 && svid <= 24) || (frm == 4 && svid >= 25 && svid <= 32)) {
1460 if (!(sat = satno(SYS_GPS, svid))) {
1461 return 0;
1462 }
1463 alm[sat - 1].sat = sat;
1464 decode_alm_sat(buff, 0, alm + sat);
1465 return 1;
1466 } else if (frm == 5 && svid == 51) { /* subframe 5 page 25 */
1467 i = 56;
1468 toas = getbitu(buff, i, 8) * 4096;
1469 i += 8;
1470 week = getbitu(buff, i, 8);
1471 i += 8;
1472 for (j = 0; j < 24; j++, i += 6) {
1473 if (!(sat = satno(SYS_GPS, j + 1))) {
1474 continue;
1475 }
1476 alm[sat - 1].svh = getbitu(buff, i, 6);
1477 }
1478 for (j = 0; j < 32; j++) {
1479 if (!(sat = satno(SYS_GPS, j + 1)) || alm[sat - 1].sat != sat || alm[sat - 1].toas != toas) {
1480 continue;
1481 }
1482 alm[sat - 1].week = adjgpsweek(week);
1483 alm[sat - 1].toa = gpst2time(alm[sat - 1].week, toas);
1484 }
1485 return 1;
1486 } else if (frm == 4 && svid == 63) { /* subframe 4 page 25 */
1487 i = 186;
1488 for (j = 0; j < 8; j++, i += 6) {
1489 if (!(sat = satno(SYS_GPS, j + 25))) {
1490 continue;
1491 }
1492 alm[sat - 1].svh = getbitu(buff, i, 6);
1493 }
1494 return 1;
1495 }
1496 return 0;
1497}
1498/* decode QZSS almanac/health ------------------------------------------------*/
1499static int decode_alm_qzs(const uint8_t* buff, alm_t* alm) {
1500 int i, j, sat, toas, week, svid = getbitu(buff, 50, 6);
1501
1502 trace(NULL, 4, "decode_alm_qzs:\n");
1503
1504 if (svid >= 1 && svid <= 9) {
1505 if (!(sat = satno(SYS_QZS, 192 + svid))) {
1506 return 0;
1507 }
1508 alm[sat - 1].sat = sat;
1509 decode_alm_sat(buff, (svid <= 6) ? 1 : 2, alm + sat);
1510 return 1;
1511 } else if (svid == 51) {
1512 i = 56;
1513 toas = getbitu(buff, i, 8) * 4096;
1514 i += 8;
1515 week = getbitu(buff, i, 8);
1516 i += 8;
1517 for (j = 0; j < 10; j++, i += 6) {
1518 if (!(sat = satno(SYS_QZS, 193 + j))) {
1519 continue;
1520 }
1521 alm[sat - 1].svh = getbitu(buff, i, 6);
1522 }
1523 for (j = 0; j < 10; j++) {
1524 if (!(sat = satno(SYS_QZS, 193 + j)) || alm[sat - 1].sat != sat || alm[sat - 1].toas != toas) {
1525 continue;
1526 }
1527 alm[sat - 1].week = adjgpsweek(week);
1528 alm[sat - 1].toa = gpst2time(alm[sat - 1].week, toas);
1529 }
1530 return 1;
1531 }
1532 return 0;
1533}
1534/* decode GPS/QZSS almanac/health --------------------------------------------*/
1535static int decode_frame_alm(const uint8_t* buff, alm_t* alm) {
1536 int frm, dataid, ret = 0;
1537
1538 trace(NULL, 4, "decode_frame_alm:\n");
1539
1540 for (frm = 4, buff += 90; frm <= 5; frm++, buff += 30) { /* subframe 4/5 */
1541 if (getbitu(buff, 43, 3) != frm) {
1542 continue;
1543 }
1544 dataid = getbitu(buff, 48, 2);
1545
1546 if (dataid == 1) { /* GPS */
1547 ret |= decode_alm_gps(buff, frm, alm);
1548 } else if (dataid == 3) { /* QZSS */
1549 ret |= decode_alm_qzs(buff, alm);
1550 }
1551 }
1552 return ret;
1553}
1554/* decode GPS/QZSS iono parameters -------------------------------------------*/
1555static int decode_frame_ion(const uint8_t* buff, double* ion) {
1556 int i, frm;
1557
1558 trace(NULL, 4, "decode_frame_ion:\n");
1559
1560 /* subframe 4/5 and svid=56 (page18) (wide area for QZSS) */
1561 for (frm = 4, buff += 90; frm <= 5; frm++, buff += 30) {
1562 if (frm == 5 && getbitu(buff, 48, 2) == 1) {
1563 continue;
1564 }
1565 if (getbitu(buff, 43, 3) != frm || getbitu(buff, 50, 6) != 56) {
1566 continue;
1567 }
1568 i = 56;
1569 ion[0] = getbits(buff, i, 8) * P2_30;
1570 i += 8;
1571 ion[1] = getbits(buff, i, 8) * P2_27;
1572 i += 8;
1573 ion[2] = getbits(buff, i, 8) * P2_24;
1574 i += 8;
1575 ion[3] = getbits(buff, i, 8) * P2_24;
1576 i += 8;
1577 ion[4] = getbits(buff, i, 8) * P2P11;
1578 i += 8;
1579 ion[5] = getbits(buff, i, 8) * P2P14;
1580 i += 8;
1581 ion[6] = getbits(buff, i, 8) * P2P16;
1582 i += 8;
1583 ion[7] = getbits(buff, i, 8) * P2P16;
1584 return 1;
1585 }
1586 return 0;
1587}
1588/* decode GPS/QZSS UTC parameters --------------------------------------------*/
1589static int decode_frame_utc(const uint8_t* buff, double* utc) {
1590 int i, frm;
1591
1592 trace(NULL, 4, "decode_frame_utc:\n");
1593
1594 /* subframe 4/5 and svid=56 (page18) */
1595 for (frm = 4, buff += 90; frm <= 5; frm++, buff += 30) {
1596 if (frm == 5 && getbitu(buff, 48, 2) == 1) {
1597 continue;
1598 }
1599 if (getbitu(buff, 43, 3) != frm || getbitu(buff, 50, 6) != 56) {
1600 continue;
1601 }
1602 i = 120;
1603 utc[1] = getbits(buff, i, 24) * P2_50;
1604 i += 24; /* A1 (s) */
1605 utc[0] = getbits(buff, i, 32) * P2_30;
1606 i += 32; /* A0 (s) */
1607 utc[2] = getbitu(buff, i, 8) * P2P12;
1608 i += 8; /* tot (s) */
1609 utc[3] = getbitu(buff, i, 8);
1610 i += 8; /* WNt */
1611 utc[4] = getbits(buff, i, 8);
1612 i += 8; /* dt_LS */
1613 utc[5] = getbitu(buff, i, 8);
1614 i += 8; /* WN_LSF */
1615 utc[6] = getbitu(buff, i, 8);
1616 i += 8; /* DN */
1617 utc[7] = getbits(buff, i, 8); /* dt_LSF */
1618 return 1;
1619 }
1620 return 0;
1621}
1622/* decode GPS/QZSS navigation data ---------------------------------------------
1623 * decode GPS/QZSS navigation data (ref [1],[4])
1624 * args : uint8_t *buff I GPS/QZSS navigation data (w/o parity bits)
1625 * buff[ 0- 29]: subframe 1 (240 bits)
1626 * buff[ 30- 59]: subframe 2
1627 * buff[ 60- 89]: subframe 3
1628 * buff[ 90-119]: subframe 4
1629 * buff[120-149]: subframe 5
1630 * eph_t *eph IO GPS/QZSS ephemeris (NULL: not output)
1631 * alm_t *alm IO GPS/QZSS almanac/health (NULL: not output)
1632 * alm[sat-1]: almanac/health (sat=sat no)
1633 * double *ion IO GPS/QZSS iono parameters (NULL: not output)
1634 * ion[0-3]: alpha_0,...,alpha_3
1635 * ion[4-7]: beta_0,...,beta_3
1636 * double *utc IO GPST/QZSS UTC parameters (NULL: not output)
1637 * utc[0-3]: A0,A1,tot,WNt(8bit)
1638 * utc[4-7]: dt_LS,WN_LSF(8bit),DN,dt_LSF
1639 * return : status (1:ok,0:error or no data)
1640 * notes : use CPU time to resolve modulo 1024 ambiguity of the week number
1641 * see ref [1]
1642 *-----------------------------------------------------------------------------*/
1643extern int decode_frame(const uint8_t* buff, eph_t* eph, alm_t* alm, double* ion, double* utc) {
1644 trace(NULL, 4, "decode_frame:\n");
1645
1646 if (eph && !decode_frame_eph(buff, eph)) {
1647 return 0;
1648 }
1649 if (alm && !decode_frame_alm(buff, alm)) {
1650 return 0;
1651 }
1652 if (ion && !decode_frame_ion(buff, ion)) {
1653 return 0;
1654 }
1655 if (utc && !decode_frame_utc(buff, utc)) {
1656 return 0;
1657 }
1658 return 1;
1659}
1660/* route a QZSS L6 frame from a receiver container (UBX/SBF) ----------------*/
1661extern int decode_qzss_l6frame(rtcm_t* rtcm, int is_l6d) {
1662 l6_header_t hdr;
1663 int ret;
1664
1665 l6_parse_header(rtcm->buff, &hdr);
1666 if (!l6_service_expected(&hdr)) {
1667 trace(NULL, 3, "L6 frame: prn=%d service=%s not nominal for this PRN\n", hdr.prn, l6_service_name(hdr.svc));
1668 }
1669 switch (hdr.svc) {
1670 case L6_SVC_CLAS:
1671 return 10;
1672 case L6_SVC_MADOCA_IONO:
1673 return 16;
1674 case L6_SVC_QZNMA:
1675 return 17;
1676 case L6_SVC_MADOCA:
1677 /* remap "L6E SSR decoded" (10) so it is not read as a CLAS frame */
1678 ret = decode_qzss_l6emsg(rtcm);
1679 return ret == 10 ? 15 : ret;
1680 case L6_SVC_NULL:
1681 /* L6D: dropped, so it never reaches the CLAS demux (msgid 0 would
1682 * read as transmit pattern 0) nor the iono decoder (#344).
1683 * L6E: the MADOCA decoder sees the alert flag and returns -1
1684 * without clearing corrections (IS-QZSS-MDC-004 5.4.2). */
1685 if (is_l6d) {
1686 trace(NULL, 2, "L6 frame: null message prn=%d dropped\n", hdr.prn);
1687 return 0;
1688 }
1689 ret = decode_qzss_l6emsg(rtcm);
1690 return ret == 10 ? 15 : ret;
1691 default:
1692 return 0;
1693 }
1694}
1695/* initialize receiver raw data control ----------------------------------------
1696 * initialize receiver raw data control struct and reallocate observation and
1697 * epheris buffer
1698 * args : raw_t *raw IO receiver raw data control struct
1699 * int format I stream format (STRFMT_???)
1700 * return : status (1:ok,0:memory allocation error)
1701 *-----------------------------------------------------------------------------*/
1702extern int init_raw(raw_t* raw, int format) {
1703 gtime_t time0 = {0};
1704 obsd_t data0 = {{0}};
1705 eph_t eph0 = {0, -1, -1};
1706 alm_t alm0 = {0, -1};
1707 geph_t geph0 = {0, -1};
1708 seph_t seph0 = {0};
1709 sbsmsg_t sbsmsg0 = {0};
1710 int i, j, ret = 1;
1711
1712 trace(NULL, 3, "init_raw: format=%d\n", format);
1713
1714 raw->time = time0;
1715 raw->ephset = raw->ephsat = 0;
1716 raw->sbsmsg = sbsmsg0;
1717 raw->msgtype[0] = '\0';
1718 for (i = 0; i < MAXSAT; i++) {
1719 for (j = 0; j < 380; j++) {
1720 raw->subfrm[i][j] = 0;
1721 }
1722 for (j = 0; j < NFREQ + NEXOBS; j++) {
1723 raw->tobs[i][j] = time0;
1724 raw->lockt[i][j] = 0.0;
1725 raw->halfc[i][j] = 0;
1726 }
1727 raw->icpp[i] = raw->off[i] = raw->prCA[i] = raw->dpCA[i] = 0.0;
1728 }
1729 for (i = 0; i < MAXOBS; i++) {
1730 raw->freqn[i] = 0;
1731 }
1732 raw->icpc = 0.0;
1733 raw->nbyte = raw->len = 0;
1734 raw->iod = raw->flag = raw->tbase = raw->outtype = 0;
1735 raw->tod = -1;
1736 for (i = 0; i < MAXRAWLEN; i++) {
1737 raw->buff[i] = 0;
1738 }
1739 raw->opt[0] = '\0';
1740 memset(raw->sigcfg, 0, sizeof(raw->sigcfg)); /* #189: default = no sigcfg (legacy -R/-G path) */
1741 raw->sigcfg_set = 0;
1742 raw->format = -1;
1743
1744 raw->obs.data = NULL;
1745 raw->obuf.data = NULL;
1746 raw->nav.eph = NULL;
1747 raw->nav.alm = NULL;
1748 raw->nav.geph = NULL;
1749 raw->nav.seph = NULL;
1750 raw->rcv_data = NULL;
1751
1752 if (!(raw->obs.data = (obsd_t*)malloc(sizeof(obsd_t) * MAXOBS)) ||
1753 !(raw->obuf.data = (obsd_t*)malloc(sizeof(obsd_t) * MAXOBS)) ||
1754 !(raw->nav.eph = (eph_t*)malloc(sizeof(eph_t) * MAXSAT * 2)) ||
1755 !(raw->nav.alm = (alm_t*)malloc(sizeof(alm_t) * MAXSAT)) ||
1756 !(raw->nav.geph = (geph_t*)malloc(sizeof(geph_t) * NSATGLO)) ||
1757 !(raw->nav.seph = (seph_t*)malloc(sizeof(seph_t) * NSATSBS * 2))) {
1758 free_raw(raw);
1759 return 0;
1760 }
1761 raw->obs.n = 0;
1762 raw->obuf.n = 0;
1763 raw->nav.n = MAXSAT * 2;
1764 raw->nav.na = MAXSAT;
1765 raw->nav.ng = NSATGLO;
1766 raw->nav.ns = NSATSBS * 2;
1767 for (i = 0; i < MAXOBS; i++) {
1768 raw->obs.data[i] = data0;
1769 }
1770 for (i = 0; i < MAXOBS; i++) {
1771 raw->obuf.data[i] = data0;
1772 }
1773 for (i = 0; i < MAXSAT * 2; i++) {
1774 raw->nav.eph[i] = eph0;
1775 }
1776 for (i = 0; i < MAXSAT; i++) {
1777 raw->nav.alm[i] = alm0;
1778 }
1779 for (i = 0; i < NSATGLO; i++) {
1780 raw->nav.geph[i] = geph0;
1781 }
1782 for (i = 0; i < NSATSBS * 2; i++) {
1783 raw->nav.seph[i] = seph0;
1784 }
1785 raw->sta.name[0] = raw->sta.marker[0] = '\0';
1786 raw->sta.antdes[0] = raw->sta.antsno[0] = '\0';
1787 raw->sta.rectype[0] = raw->sta.recver[0] = raw->sta.recsno[0] = '\0';
1788 raw->sta.antsetup = raw->sta.itrf = raw->sta.deltype = 0;
1789 for (i = 0; i < 3; i++) {
1790 raw->sta.pos[i] = raw->sta.del[i] = 0.0;
1791 }
1792 raw->sta.hgt = 0.0;
1793
1794 /* initialize receiver dependent data */
1795 raw->format = format;
1796 switch (format) {
1797 case STRFMT_RT17:
1798 ret = init_rt17(raw);
1799 break;
1800 }
1801 if (!ret) {
1802 free_raw(raw);
1803 return 0;
1804 }
1805 return 1;
1806}
1807/* free receiver raw data control ----------------------------------------------
1808 * free observation and ephemeris buffer in receiver raw data control struct
1809 * args : raw_t *raw IO receiver raw data control struct
1810 * return : none
1811 *-----------------------------------------------------------------------------*/
1812extern void free_raw(raw_t* raw) {
1813 trace(NULL, 3, "free_raw:\n");
1814
1815 free(raw->obs.data);
1816 raw->obs.data = NULL;
1817 raw->obs.n = 0;
1818 free(raw->obuf.data);
1819 raw->obuf.data = NULL;
1820 raw->obuf.n = 0;
1821 free(raw->nav.eph);
1822 raw->nav.eph = NULL;
1823 raw->nav.n = 0;
1824 free(raw->nav.alm);
1825 raw->nav.alm = NULL;
1826 raw->nav.na = 0;
1827 free(raw->nav.geph);
1828 raw->nav.geph = NULL;
1829 raw->nav.ng = 0;
1830 free(raw->nav.seph);
1831 raw->nav.seph = NULL;
1832 raw->nav.ns = 0;
1833
1834 /* free receiver dependent data */
1835 switch (raw->format) {
1836 case STRFMT_RT17:
1837 free_rt17(raw);
1838 break;
1839 }
1840 raw->rcv_data = NULL;
1841}
1842/* input receiver raw data from stream -----------------------------------------
1843 * fetch next receiver raw data and input a message from stream
1844 * args : raw_t *raw IO receiver raw data control struct
1845 * rtcm_t *rtcm IO rtcm control struct
1846 * int format I receiver raw data format (STRFMT_???)
1847 * uint8_t data I stream data (1 byte)
1848 * return : status (-1: error message, 0: no message, 1: input observation data,
1849 * 2: input ephemeris, 3: input sbas message,
1850 * 9: input ion/utc parameter)
1851 *-----------------------------------------------------------------------------*/
1852extern int input_raw(raw_t* raw, rtcm_t* rtcm, int format, uint8_t data) {
1853 trace(NULL, 5, "input_raw: format=%d data=0x%02x\n", format, data);
1854
1855 switch (format) {
1856 case STRFMT_OEM4:
1857 return input_oem4(raw, data);
1858 case STRFMT_OEM3:
1859 return input_oem3(raw, data);
1860 case STRFMT_UBX:
1861 return input_ubx(raw, rtcm, data);
1862 case STRFMT_SS2:
1863 return input_ss2(raw, data);
1864 case STRFMT_CRES:
1865 return input_cres(raw, data);
1866 case STRFMT_STQ:
1867 return input_stq(raw, data);
1868 case STRFMT_JAVAD:
1869 return input_javad(raw, data);
1870 case STRFMT_NVS:
1871 return input_nvs(raw, data);
1872 case STRFMT_BINEX:
1873 return input_bnx(raw, data);
1874 case STRFMT_RT17:
1875 return input_rt17(raw, data);
1876 case STRFMT_SEPT:
1877 return input_sbf(raw, rtcm, data);
1878 }
1879 return 0;
1880}
1881/* input receiver raw data from file -------------------------------------------
1882 * fetch next receiver raw data and input a message from file
1883 * args : raw_t *raw IO receiver raw data control struct
1884 * rtcm_t *rtcm IO rtcm control struct
1885 * int format I receiver raw data format (STRFMT_???)
1886 * FILE *fp I file pointer
1887 * return : status(-2: end of file/format error, -1...31: same as above)
1888 *-----------------------------------------------------------------------------*/
1889extern int input_rawf(raw_t* raw, rtcm_t* rtcm, int format, FILE* fp) {
1890 trace(NULL, 4, "input_rawf: format=%d\n", format);
1891
1892 switch (format) {
1893 case STRFMT_OEM4:
1894 return input_oem4f(raw, fp);
1895 case STRFMT_OEM3:
1896 return input_oem3f(raw, fp);
1897 case STRFMT_UBX:
1898 return input_ubxf(raw, rtcm, fp);
1899 case STRFMT_SS2:
1900 return input_ss2f(raw, fp);
1901 case STRFMT_CRES:
1902 return input_cresf(raw, fp);
1903 case STRFMT_STQ:
1904 return input_stqf(raw, fp);
1905 case STRFMT_JAVAD:
1906 return input_javadf(raw, fp);
1907 case STRFMT_NVS:
1908 return input_nvsf(raw, fp);
1909 case STRFMT_BINEX:
1910 return input_bnxf(raw, fp);
1911 case STRFMT_RT17:
1912 return input_rt17f(raw, fp);
1913 case STRFMT_SEPT:
1914 return input_sbff(raw, rtcm, fp);
1915 }
1916 return -2;
1917}
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 MAXSAT
Definition mrtk_coords.c:45
#define SYS_GPS
Definition mrtk_eph.c:65
#define SYS_QZS
Definition mrtk_eph.c:69
#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...
#define NSATSBS
#define MAXOBS
#define MAXRAWLEN
#define NSATGLO
int l6_service_expected(const l6_header_t *h)
Test whether a classified frame matches the nominal assignment of its PRN.
Definition mrtk_l6.c:85
int l6_parse_header(const uint8_t *frame, l6_header_t *h)
Parse the header of one L6 frame and classify its service.
Definition mrtk_l6.c:44
const char * l6_service_name(l6_service_t svc)
Short name of an L6 service, for logs.
Definition mrtk_l6.c:162
MRTKLIB L6 Module — QZSS L6 frame header parsing.
@ L6_SVC_NULL
Definition mrtk_l6.h:60
@ L6_SVC_QZNMA
Definition mrtk_l6.h:64
@ L6_SVC_CLAS
Definition mrtk_l6.h:61
@ L6_SVC_MADOCA
Definition mrtk_l6.h:62
@ L6_SVC_MADOCA_IONO
Definition mrtk_l6.h:63
int decode_qzss_l6emsg(rtcm_t *rtcm)
Decode QZSS L6E message and convert to RTCM SSR.
MRTKLIB MADOCA-PPP Module — QZSS L6E CSSR message decode functions.
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.
MRTKLIB Observation Module — Observation data types and utility functions.
static rtcm_t * rtcm
#define N4(opt)
Definition mrtk_ppp.c:221
#define NT(opt)
int input_bnx(raw_t *raw, uint8_t data)
int input_bnxf(raw_t *raw, FILE *fp)
int input_cres(raw_t *raw, uint8_t data)
int input_cresf(raw_t *raw, FILE *fp)
int input_javadf(raw_t *raw, FILE *fp)
int input_javad(raw_t *raw, uint8_t data)
int input_oem4(raw_t *raw, uint8_t data)
int input_oem4f(raw_t *raw, FILE *fp)
int input_oem3f(raw_t *raw, FILE *fp)
int input_oem3(raw_t *raw, uint8_t data)
int input_nvs(raw_t *raw, uint8_t data)
int input_nvsf(raw_t *raw, FILE *fp)
void free_rt17(raw_t *Raw)
int input_rt17f(raw_t *Raw, FILE *fp)
int init_rt17(raw_t *Raw)
int input_rt17(raw_t *Raw, uint8_t Data)
int input_sbff(raw_t *raw, rtcm_t *rtcm, FILE *fp)
int input_sbf(raw_t *raw, rtcm_t *rtcm, uint8_t data)
int input_stqf(raw_t *raw, FILE *fp)
int input_stq(raw_t *raw, uint8_t data)
int input_ss2f(raw_t *raw, FILE *fp)
int input_ss2(raw_t *raw, uint8_t data)
int input_ubxf(raw_t *raw, rtcm_t *rtcm, FILE *fp)
int input_ubx(raw_t *raw, rtcm_t *rtcm, uint8_t data)
#define P2_31
Definition mrtk_rcvraw.c:56
#define P2_15
Definition mrtk_rcvraw.c:46
#define P2_28
Definition mrtk_rcvraw.c:72
#define P2_41
Definition mrtk_rcvraw.c:74
static int decode_irn_eph(const uint8_t *buff, eph_t *eph)
#define P2P12
Definition mrtk_rcvraw.c:81
static int decode_bds_d2_utc(const uint8_t *buff, double *utc)
static int decode_gal_fnav_ion(const uint8_t *buff, double *ion)
static int decode_bds_d1_utc(const uint8_t *buff, double *utc)
static int decode_glostr_eph(const uint8_t *buff, geph_t *geph)
#define P2_55
Definition mrtk_rcvraw.c:64
static double getbitg(const uint8_t *buff, int pos, int len)
static int decode_gal_fnav_utc(const uint8_t *buff, double *utc)
static uint32_t getbitu3(const uint8_t *buff, int p1, int l1, int p2, int l2, int p3, int l3)
int decode_qzss_l6frame(rtcm_t *rtcm, int is_l6d)
Route one QZSS L6 frame received in a UBX/SBF container.
void free_raw(raw_t *raw)
Free receiver raw data control struct.
#define P2_38
Definition mrtk_rcvraw.c:60
static int decode_frame_alm(const uint8_t *buff, alm_t *alm)
#define P2_50
Definition mrtk_rcvraw.c:63
#define P2_29
Definition mrtk_rcvraw.c:54
#define P2_51
Definition mrtk_rcvraw.c:76
int input_rawf(raw_t *raw, rtcm_t *rtcm, int format, FILE *fp)
Input receiver raw data from file.
static int decode_frame_ion(const uint8_t *buff, double *ion)
#define P2_66
Definition mrtk_rcvraw.c:78
#define P2_24
Definition mrtk_rcvraw.c:52
static int decode_glostr_utc(const uint8_t *buff, double *utc)
static uint32_t merge_two_u(uint32_t a, uint32_t b, int n)
static uint32_t getbitu2(const uint8_t *buff, int p1, int l1, int p2, int l2)
Definition mrtk_rcvraw.c:89
#define P2_14
Definition mrtk_rcvraw.c:70
static int decode_alm_gps(const uint8_t *buff, int frm, alm_t *alm)
int decode_gal_fnav(const uint8_t *buff, eph_t *eph, double *ion, double *utc)
int decode_frame(const uint8_t *buff, eph_t *eph, alm_t *alm, double *ion, double *utc)
#define P2_21
Definition mrtk_rcvraw.c:50
static int decode_gal_inav_eph(const uint8_t *buff, eph_t *eph)
static int decode_gal_inav_ion(const uint8_t *buff, double *ion)
int input_raw(raw_t *raw, rtcm_t *rtcm, int format, uint8_t data)
Input receiver raw data from stream (byte-by-byte).
static int decode_frame_utc(const uint8_t *buff, double *utc)
static int decode_irn_utc(const uint8_t *buff, double *utc)
static int decode_alm_qzs(const uint8_t *buff, alm_t *alm)
static int decode_irn_ion(const uint8_t *buff, double *ion)
static int32_t getbits2(const uint8_t *buff, int p1, int l1, int p2, int l2)
Definition mrtk_rcvraw.c:92
#define P2P16
Definition mrtk_rcvraw.c:84
#define P2_23
Definition mrtk_rcvraw.c:51
#define P2_8
Definition mrtk_rcvraw.c:68
static int32_t getbits3(const uint8_t *buff, int p1, int l1, int p2, int l2, int p3, int l3)
#define P2_43
Definition mrtk_rcvraw.c:62
#define P2_40
Definition mrtk_rcvraw.c:61
static int decode_gal_fnav_eph(const uint8_t *buff, eph_t *eph)
int test_glostr(const uint8_t *buff)
#define P2_17
Definition mrtk_rcvraw.c:47
#define P2_59
Definition mrtk_rcvraw.c:77
#define P2_46
Definition mrtk_rcvraw.c:75
int decode_glostr(const uint8_t *buff, geph_t *geph, double *utc)
static void decode_alm_sat(const uint8_t *buff, int type, alm_t *alm)
#define P2P14
Definition mrtk_rcvraw.c:82
#define P2_11
Definition mrtk_rcvraw.c:45
#define P2_19
Definition mrtk_rcvraw.c:48
int decode_bds_d2(const uint8_t *buff, eph_t *eph, double *utc)
#define P2_27
Definition mrtk_rcvraw.c:53
#define P2P11
Definition mrtk_rcvraw.c:80
int decode_gal_inav(const uint8_t *buff, eph_t *eph, double *ion, double *utc)
int decode_bds_d1(const uint8_t *buff, eph_t *eph, double *ion, double *utc)
static int32_t merge_two_s(int32_t a, uint32_t b, int n)
#define P2_33
Definition mrtk_rcvraw.c:58
#define SQR(x)
Definition mrtk_rcvraw.c:86
#define P2_18
Definition mrtk_rcvraw.c:71
int decode_irn_nav(const uint8_t *buff, eph_t *eph, double *ion, double *utc)
#define P2_6
Definition mrtk_rcvraw.c:44
#define P2_20
Definition mrtk_rcvraw.c:49
static int decode_bds_d2_eph(const uint8_t *buff, eph_t *eph)
int init_raw(raw_t *raw, int format)
Initialize receiver raw data control struct.
#define P2_9
Definition mrtk_rcvraw.c:69
#define P2_34
Definition mrtk_rcvraw.c:73
#define P2_32
Definition mrtk_rcvraw.c:57
#define P2_5
Definition mrtk_rcvraw.c:43
static int decode_gal_inav_utc(const uint8_t *buff, double *utc)
#define P2_30
Definition mrtk_rcvraw.c:55
static int decode_bds_d1_eph(const uint8_t *buff, eph_t *eph)
#define P2_35
Definition mrtk_rcvraw.c:59
static int decode_frame_eph(const uint8_t *buff, eph_t *eph)
#define P2_68
Definition mrtk_rcvraw.c:79
static int decode_bds_d1_ion(const uint8_t *buff, double *ion)
#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_JAVAD
Definition mrtk_rcvraw.h:57
#define STRFMT_OEM3
Definition mrtk_rcvraw.h:52
#define STRFMT_NVS
Definition mrtk_rcvraw.h:58
#define STRFMT_CRES
Definition mrtk_rcvraw.h:55
#define STRFMT_SS2
Definition mrtk_rcvraw.h:54
#define STRFMT_UBX
Definition mrtk_rcvraw.h:53
#define STRFMT_OEM4
Definition mrtk_rcvraw.h:51
#define STRFMT_BINEX
Definition mrtk_rcvraw.h:59
#define STRFMT_RT17
Definition mrtk_rcvraw.h:60
#define STRFMT_STQ
Definition mrtk_rcvraw.h:56
#define STRFMT_SEPT
Definition mrtk_rcvraw.h:61
MRTKLIB RTCM Module — RTCM message types and functions.
gtime_t gst2time(int week, double sec)
Convert Galileo system time week/tow to gtime_t.
Definition mrtk_time.c:197
gtime_t bdt2time(int week, double sec)
Convert BeiDou time week/tow to gtime_t.
Definition mrtk_time.c:229
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
gtime_t gpst2utc(gtime_t t)
Convert GPS time to UTC considering leap seconds.
Definition mrtk_time.c:422
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
int adjgpsweek(int week)
Adjust GPS week number using CPU time.
Definition mrtk_time.c:553
gtime_t timeadd(gtime_t t, double sec)
Add seconds to gtime_t.
Definition mrtk_time.c:265
gtime_t bdt2gpst(gtime_t t)
Convert BeiDou time to GPS time.
Definition mrtk_time.c:465
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 almanac type.
Definition mrtk_eph.h:49
gtime_t toa
Definition mrtk_eph.h:54
double e
Definition mrtk_eph.h:55
int svh
Definition mrtk_eph.h:51
double i0
Definition mrtk_eph.h:55
double M0
Definition mrtk_eph.h:55
int week
Definition mrtk_eph.h:53
double toas
Definition mrtk_eph.h:56
double A
Definition mrtk_eph.h:55
int sat
Definition mrtk_eph.h:50
double OMGd
Definition mrtk_eph.h:55
double f0
Definition mrtk_eph.h:57
double OMG0
Definition mrtk_eph.h:55
double f1
Definition mrtk_eph.h:57
double omg
Definition mrtk_eph.h:55
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 almanac type.
Definition mrtk_eph.h:63
int Mn
Definition mrtk_eph.h:66
double omgn
Definition mrtk_eph.h:70
int Hn
Definition mrtk_eph.h:67
double eccn
Definition mrtk_eph.h:70
double tn
Definition mrtk_eph.h:69
double din
Definition mrtk_eph.h:70
int sat
Definition mrtk_eph.h:64
gtime_t toa
Definition mrtk_eph.h:68
double dTn
Definition mrtk_eph.h:70
int Cn
Definition mrtk_eph.h:65
double lamn
Definition mrtk_eph.h:70
double taun
Definition mrtk_eph.h:71
double ddTn
Definition mrtk_eph.h:70
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 sva
Definition mrtk_eph.h:117
int flags
Definition mrtk_eph.h:116
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
Decoded L6 frame header. Raw bit fields; no service-specific remapping.
Definition mrtk_l6.h:68
uint8_t prn
Definition mrtk_l6.h:70
l6_service_t svc
Definition mrtk_l6.h:79
int ng
Definition mrtk_nav.h:394
seph_t * seph
Definition mrtk_nav.h:408
int na
Definition mrtk_nav.h:398
geph_t * geph
Definition mrtk_nav.h:407
alm_t * alm
Definition mrtk_nav.h:411
eph_t * eph
Definition mrtk_nav.h:400
int ns
Definition mrtk_nav.h:395
int n
Definition mrtk_nav.h:393
obsd_t * data
Definition mrtk_obs.h:61
int n
Definition mrtk_obs.h:60
Observation data record.
Definition mrtk_obs.h:44
Receiver raw data control type.
Definition mrtk_rcvraw.h:78
sbsmsg_t sbsmsg
Definition mrtk_rcvraw.h:87
uint8_t subfrm[MAXSAT][380]
Definition mrtk_rcvraw.h:89
nav_t nav
Definition mrtk_rcvraw.h:83
double icpp[MAXSAT]
Definition mrtk_rcvraw.h:91
double lockt[MAXSAT][5+5]
Definition mrtk_rcvraw.h:90
mrtk_sigcfg_t sigcfg[MRTK_NSYS]
void * rcv_data
int tbase
Definition mrtk_rcvraw.h:99
int ephset
Definition mrtk_rcvraw.h:86
char freqn[MAXOBS]
Definition mrtk_rcvraw.h:94
int outtype
int sigcfg_set
obs_t obs
Definition mrtk_rcvraw.h:81
int format
int len
Definition mrtk_rcvraw.h:96
uint8_t buff[MAXRAWLEN]
char msgtype[256]
Definition mrtk_rcvraw.h:88
double prCA[MAXSAT]
Definition mrtk_rcvraw.h:92
int nbyte
Definition mrtk_rcvraw.h:95
int flag
uint8_t halfc[MAXSAT][5+5]
Definition mrtk_rcvraw.h:93
char opt[256]
double dpCA[MAXSAT]
Definition mrtk_rcvraw.h:92
double icpc
Definition mrtk_rcvraw.h:91
sta_t sta
Definition mrtk_rcvraw.h:84
gtime_t tobs[MAXSAT][5+5]
Definition mrtk_rcvraw.h:80
int ephsat
Definition mrtk_rcvraw.h:85
double off[MAXSAT]
Definition mrtk_rcvraw.h:91
int iod
Definition mrtk_rcvraw.h:97
gtime_t time
Definition mrtk_rcvraw.h:79
int tod
Definition mrtk_rcvraw.h:98
obs_t obuf
Definition mrtk_rcvraw.h:82
RTCM control struct type.
Definition mrtk_rtcm.h:50
SBAS ephemeris type.
Definition mrtk_eph.h:130
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