MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_madoca_iono.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_madoca_iono.c : QZSS L6D MADOCA-PPP wide area ionospheric correction
3 * message decode functions
4 *
5 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
6 * Copyright (C) 2023-2025 Cabinet Office, Japan
7 * Copyright (C) 2024-2025 Lighthouse Technology & Consulting Co. Ltd.
8 * Copyright (C) 2023-2025 Japan Aerospace Exploration Agency
9 * Copyright (C) 2023-2025 TOSHIBA ELECTRONIC TECHNOLOGIES CORPORATION
10 * Copyright (C) 2015- Mitsubishi Electric Corp.
11 * Copyright (C) 2014 Geospatial Information Authority of Japan
12 * Copyright (C) 2014 T.SUZUKI
13 * Copyright (C) 2007-2023 T.TAKASU
14 *
15 * SPDX-License-Identifier: BSD-2-Clause
16 *
17 * references :
18 * [1] CAO IS-QZSS-MDC-002, November, 2023
19 *
20 * version : $Revision:$ $Date:$
21 * history : 2024/01/10 1.0 new, for MADOCALIB from TETC original tools.
22 * 2024/02/10 1.1 fix bug on when the last byte of R-S is the same as
23 * the first byte of the preamble in input_qzssl6d()
24 * 2024/07/23 1.2 delete unnecessary constant.
25 * 2024/09/27 1.3 fix bug for incorrect maxframe calculation
26 * in decode_qzss_l6dmsg().
27 * support multiple inputs of l6d stream.
28 * 2025/xx/xx ported to MRTKLIB (headers, trace API)
29 *-----------------------------------------------------------------------------*/
30#include <math.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include "mrtklib/mrtk_bits.h"
36#include "mrtklib/mrtk_const.h"
37#include "mrtklib/mrtk_l6.h"
38#include "mrtklib/mrtk_nav.h"
39#include "mrtklib/mrtk_ppp.h"
40#include "mrtklib/mrtk_trace.h"
41
42/* forward declarations */
43extern int satsys(int sat, int* prn);
44extern void satno2id(int sat, char* id);
45extern int satno(int sys, int prn);
46extern char* time_str(gtime_t t, int n);
47extern double timediff(gtime_t t1, gtime_t t2);
48extern double time2gpst(gtime_t t, int* week);
49extern gtime_t gpst2time(int week, double sec);
50extern gtime_t utc2gpst(gtime_t t);
51extern gtime_t timeget(void);
52
53/* constants -----------------------------------------------------------------*/
54
55#define MIONO_MAX_FRAME 40 /* dependent on Length of Correction Messages */
56
57#define MIONO_MT_COV 1 /* STEC Coverage Message Type */
58#define MIONO_MT_COR 2 /* STEC Correction Message Type */
59
60#define MIONO_MAX_SYS 5 /* GNSS ID (Table 6.3.2-8) */
61#define MIONO_SYS_GPS 0
62#define MIONO_SYS_GLO 1
63#define MIONO_SYS_GAL 2
64#define MIONO_SYS_BDS 3
65#define MIONO_SYS_QZS 4
66
67#define MIONO_INVALID_14BIT -8192 /* Invalid Value (Table 6.3.2-9) */
68#define MIONO_INVALID_12BIT -2048
69#define MIONO_INVALID_10BIT -512
70#define MIONO_INVALID_8BIT -128
71
72#define SQR(x) ((x) * (x))
73
74typedef struct {
75 gtime_t gt; /* current Epoch Time 1s */
76 int mgfid; /* current Msg. Gen. Facility ID */
77 uint8_t buff[L6_FRAME_LEN * MIONO_MAX_FRAME]; /* L6D Message */
78 int ibuff; /* indicate the end of buff */
79 int maxframe; /* set framelen[first subtype] */
80 int frame; /* frame counter */
81 int tow0; /* for Hourly Epoch Time 1s */
82 int ep0; /* for Hourly Epoch Time 1s regresses check */
83 int iod; /* IOD SSR */
84} miono_t;
85
87
88/* ---------------------------------------------------------------------------*/
89static int gnssid2sys(int gnssid) {
90 switch (gnssid) {
91 case MIONO_SYS_GPS:
92 return SYS_GPS;
93 case MIONO_SYS_GLO:
94 return SYS_GLO;
95 case MIONO_SYS_GAL:
96 return SYS_GAL;
97 case MIONO_SYS_BDS:
98 return SYS_CMP;
99 case MIONO_SYS_QZS:
100 return SYS_QZS;
101 }
102 return -1;
103}
104
105/* adjust weekly rollover of gps time ----------------------------------------*/
106static void adjweek(gtime_t* gt, double tow) {
107 double tow_p;
108 int week;
109
110 /* if no time, get cpu time */
111 if (gt->time == 0) {
112 *gt = utc2gpst(timeget());
113 }
114 tow_p = time2gpst(*gt, &week);
115 if (tow < tow_p - 302400.0) {
116 tow += 604800.0;
117 } else if (tow > tow_p + 302400.0) {
118 tow -= 604800.0;
119 }
120 *gt = gpst2time(week, tow);
121}
122
123/* decode MADOCA-PPP L6D MT1 STEC coverage message ---------------------------*/
124static int decode_miono_coverage(miono_t* mi, miono_region_t* re, int i, int* imax, int* rid) {
125 int j, ep, udi, sync, iod, ralert, corlen, narea, anum, ref[2], span[2];
126
127 ep = getbitu(mi->buff, i, 20);
128 i += 20; /* GNSS Epoch Time 1s */
129 udi = getbitu(mi->buff, i, 4);
130 i += 4; /* SSR Update Interval */
131 sync = getbitu(mi->buff, i, 1);
132 i += 1; /* Multiple Message Indicator */
133 iod = getbitu(mi->buff, i, 4);
134 i += 4; /* IOD SSR */
135 *rid = getbitu(mi->buff, i, 8);
136 i += 8; /* Region ID */
137 ralert = getbitu(mi->buff, i, 1);
138 i += 1; /* Region Alert flag */
139 corlen = getbitu(mi->buff, i, 16);
140 i += 16; /* Length of Correction Messages */
141 narea = getbitu(mi->buff, i, 5);
142 i += 5; /* No. of Area */
143
144 trace(NULL, 4, "decode_miono_coverage: head ep=%d,udi=%d,sync=%d,iod=%d,rid=%d,ralert=%d,corlen=%d,narea=%d\n", ep,
145 udi, sync, iod, *rid, ralert, corlen, narea);
146
147 (void)udi;
148 (void)sync; /* suppress unused warnings */
149
150 mi->tow0 = ep / 3600 * 3600;
151 mi->ep0 = ep % 3600;
152 adjweek(&mi->gt, ep);
153 mi->iod = iod;
154 re->ralert = ralert;
155 re->narea = narea;
156 re->rvalid = 1;
157
158 for (j = 0; j < narea; j++) {
159 anum = getbitu(mi->buff, i, 5);
160 i += 5; /* Area Number */
161 re->area[anum].sid = getbitu(mi->buff, i, 1);
162 i += 1; /* Shape ID */
163 if (re->area[anum].sid == 0) {
164 ref[0] = getbits(mi->buff, i, 11);
165 i += 11; /* Reference latitude */
166 ref[1] = getbitu(mi->buff, i, 12);
167 i += 12; /* Reference longitude */
168 span[0] = getbitu(mi->buff, i, 8);
169 i += 8; /* Latitude span */
170 span[1] = getbitu(mi->buff, i, 8);
171 i += 8; /* Longitude span */
172 re->area[anum].ref[0] = ref[0] * 0.1;
173 re->area[anum].ref[1] = ref[1] * 0.1;
174 re->area[anum].span[0] = span[0] * 0.1;
175 re->area[anum].span[1] = span[1] * 0.1;
176 } else {
177 ref[0] = getbits(mi->buff, i, 15);
178 i += 15; /* Reference latitude */
179 ref[1] = getbitu(mi->buff, i, 16);
180 i += 16; /* Reference longitude */
181 span[0] = getbitu(mi->buff, i, 8);
182 i += 8; /* Effective range */
183 span[1] = 0;
184 re->area[anum].ref[0] = ref[0] * 0.01;
185 re->area[anum].ref[1] = ref[1] * 0.01;
186 re->area[anum].span[0] = span[0] * 10.0;
187 re->area[anum].span[1] = 0.0;
188 }
189 trace(NULL, 4,
190 "decode_miono_coverage: data "
191 "%s,i=%4d,rid=%3d,j=%2d,anum=%2d,sid=%d,ref=%5d,%5d,%7.2f,%7.2f,span=%4d,%4d,%6.1f,%6.1f\n",
192 time_str(mi->gt, 3), i, *rid, j, anum, re->area[anum].sid, ref[0], ref[1], re->area[anum].ref[0],
193 re->area[anum].ref[1], span[0], span[1], re->area[anum].span[0], re->area[anum].span[1]);
194 }
195 *imax = i + corlen;
196 return i;
197}
198
199/* decode MADOCA-PPP L6D MT2 STEC correction message -------------------------*/
200static int decode_miono_correction(miono_t* mi, miono_region_t* re, int i, int apply) {
201 int j, k, l, ep, udi, sync, iod, rid, anum, type;
202 int ns[MIONO_MAX_SYS], id, sqi, coef[6], offp, sat;
203 char satid[8];
204
205 ep = getbitu(mi->buff, i, 12);
206 i += 12; /* GNSS Hourly Epoch Time 1s */
207 udi = getbitu(mi->buff, i, 4);
208 i += 4; /* SSR Update Interval */
209 sync = getbitu(mi->buff, i, 1);
210 i += 1; /* Multiple Message Indicator */
211 iod = getbitu(mi->buff, i, 4);
212 i += 4; /* IOD SSR */
213 rid = getbitu(mi->buff, i, 8);
214 i += 8; /* STEC Region ID */
215 anum = getbitu(mi->buff, i, 5);
216 i += 5; /* STEC Area Number */
217 type = getbitu(mi->buff, i, 2);
218 i += 2; /* STEC Correction Type */
219
220 (void)udi;
221 (void)sync;
222 (void)rid; /* suppress unused warnings */
223
224 if (mi->tow0 < 0) {
225 trace(NULL, 2, "decode_miono_correction: %s,unprocessed coverage\n", time_str(mi->gt, 3));
226 apply = 0;
227 } else {
228 if (mi->ep0 > ep) {
229 ep += 3600;
230 }
231 adjweek(&mi->gt, mi->tow0 + ep);
232 if (mi->iod != iod) {
233 trace(NULL, 2, "decode_miono_correction: %s,iod mismatch %d != %d\n", time_str(mi->gt, 3), mi->iod, iod);
234 apply = 0;
235 }
236 }
237
238 for (j = 0; j < MIONO_MAX_SYS; j++) {
239 ns[j] = getbitu(mi->buff, i, 5);
240 i += 5; /* No. of Satellites */
241 }
242
243 trace(NULL, 4,
244 "decode_miono_correction: head ep=%d,udi=%d,sync=%d,iod=%d,rid=%d,anum=%d,type=%d,ns=%d,%d,%d,%d,%d\n", ep,
245 udi, sync, iod, rid, anum, type, ns[0], ns[1], ns[2], ns[3], ns[4]);
246
247 for (j = 0; j < MIONO_MAX_SYS; j++) {
248 for (k = 0; k < ns[j]; k++) {
249 for (l = 1; l < 6; l++) {
250 coef[l] = 0;
251 }
252 id = getbitu(mi->buff, i, 6);
253 i += 6; /* GNSS Satellite ID */
254 sqi = getbitu(mi->buff, i, 6);
255 i += 6; /* SSR STEC Quality Indicator */
256 coef[0] = getbits(mi->buff, i, 14);
257 i += 14; /* STEC Polynomial Coefficients C00 */
258 if (type > 0) {
259 coef[1] = getbits(mi->buff, i, 12);
260 i += 12; /* C01 */
261 coef[2] = getbits(mi->buff, i, 12);
262 i += 12; /* C10 */
263 }
264 if (type > 1) {
265 coef[3] = getbits(mi->buff, i, 10);
266 i += 10; /* C11 */
267 }
268 if (type > 2) {
269 coef[4] = getbits(mi->buff, i, 8);
270 i += 8; /* C02 */
271 coef[5] = getbits(mi->buff, i, 8);
272 i += 8; /* C20 */
273 }
274
275 offp = (j == MIONO_SYS_QZS) ? 192 : 0;
276 sat = satno(gnssid2sys(j), offp + id);
277 satno2id(sat, satid);
278
279 trace(NULL, 4,
280 "decode_miono_correction: data "
281 "%s,i=%4d,rid=%3d,anum=%2d,type=%d,j=%d,k=%2d,sat=%2d,%3s,sqi=0x%02X,coef=%5d,%5d,%5d,%4d,%4d,%4d,%7."
282 "2f,%7.2f,%7.2f,%7.2f,%8.3f,%8.3f\n",
283 time_str(mi->gt, 3), i, rid, anum, type, j, k, id, satid, sqi, coef[0], coef[1], coef[2], coef[3],
284 coef[4], coef[5], coef[0] * 0.05, coef[1] * 0.02, coef[2] * 0.02, coef[3] * 0.02, coef[4] * 0.005,
285 coef[5] * 0.005);
286
287 if (sat == 0) {
288 continue; /* unsupported sat */
289 }
290 if ((coef[0] == MIONO_INVALID_14BIT) || (coef[1] == MIONO_INVALID_12BIT) ||
291 (coef[2] == MIONO_INVALID_12BIT) || (coef[3] == MIONO_INVALID_10BIT) ||
292 (coef[4] == MIONO_INVALID_8BIT) || (coef[5] == MIONO_INVALID_8BIT)) {
293 continue; /* invalid value */
294 }
295
296 if (apply) {
297 re->area[anum].type = type;
298 re->area[anum].sat[sat - 1].t0 = mi->gt;
299 re->area[anum].sat[sat - 1].sqi = sqi;
300 re->area[anum].sat[sat - 1].coef[0] = coef[0] * 0.05;
301 re->area[anum].sat[sat - 1].coef[1] = coef[1] * 0.02;
302 re->area[anum].sat[sat - 1].coef[2] = coef[2] * 0.02;
303 re->area[anum].sat[sat - 1].coef[3] = coef[3] * 0.02;
304 re->area[anum].sat[sat - 1].coef[4] = coef[4] * 0.005;
305 re->area[anum].sat[sat - 1].coef[5] = coef[5] * 0.005;
306 }
307 }
308 }
309 if (apply) {
310 re->area[anum].avalid = 1;
311 }
312 return i;
313}
314
315/* decode QZSS L6D message ----------------------------------------------------
316 * decode QZSS L6D message and store ionospheric corrections
317 * args : mdcl6d_t *mdcl6d IO QZSS L6D message control struct
318 * return : status (-1: error message, 0: no message,
319 * 10: input MADOCA-PPP iono. corr. messages)
320 * note : before calling the function, init_miono()
321 *-----------------------------------------------------------------------------*/
323 unsigned int preamb, prn, type, alert, vid, mgfid, csid, anme, si;
324 l6_header_t hdr;
325 const l6_prn_info_t* info;
326 int i = 0, j, imax, n, ibuff, mn, apply, ret, optprn;
327 char* str;
328 uint8_t mask;
329 unsigned int corlen, narea;
330
331 /* decode L6 message header (49 bits) */
332 l6_parse_header(mdcl6d->buff, &hdr);
333 preamb = hdr.preamble;
334 prn = hdr.prn;
335 type = hdr.msgid; /* L6 Msg. Type ID */
336 vid = hdr.vid; /* Vendor ID(2:MADOCA-PPP) */
337 mgfid = hdr.fac; /* Msg. Gen. Facility ID(0-1:Hitachi-Ota,2-3:Kobe) */
338 csid = hdr.csid; /* Correction Service ID(0:Clock/Ephemeris,1:Iono) */
339 anme = hdr.anme; /* Applicable Nav. Msg. Ext.(0:Default,1:CNAV/CNAV2) */
340 si = hdr.sf_ind; /* Subframe Indicator(0:others,1:First Data) */
341 alert = hdr.alert; /* Alert Flag(1:Alert) */
342 i = L6_HEADER_BITS;
343
344 (void)type;
345 (void)csid;
346 (void)anme; /* suppress unused warnings */
347
348 /* decoder slot from the L6 PRN table (PRN 200/201, ref [1] Table 3-1;
349 * PRN 197 was reassigned to CLAS in IS-QZSS-MDC rev 002) */
350 info = l6_prn_info((int)prn);
351 j = info ? info->iono_slot : -1;
352 if (j < 0) {
353 trace(NULL, 3, "decode_qzss_l6dmsg: invalid prn=%d\n", prn);
354 return -1;
355 }
356
357 trace(NULL, 3,
358 "decode_qzss_l6dmsg: %s,preamb=0x%08X,prn=%d,type=0x%X(vid=%d,mgfid=%d,csid=%d,anme=%d,si=%d),alert=%d\n",
359 time_str(_miono[j].gt, 3), preamb, prn, type, vid, mgfid, csid, anme, si, alert);
360
361 if (preamb != L6_PREAMBLE) {
362 trace(NULL, 2, "decode_qzss_l6dmsg: %s,invalid preamb=0x%08X\n", time_str(_miono[j].gt, 3), preamb);
363 return -1;
364 }
365
366 if (alert) {
367 if (strstr(mdcl6d->opt, "-IGNORE_MIONO_ALERT")) {
368 trace(NULL, 3, "decode_qzss_l6dmsg: ignore alert\n");
369 } else {
370 trace(NULL, 2, "decode_qzss_l6dmsg: alert\n");
371 return -1;
372 }
373 }
374
375 if (vid != 2) {
376 return 0; /* unsupport vendor ID */
377 }
378
379 if ((str = strstr(mdcl6d->opt, "-MIONO_PRN"))) {
380 optprn = atoi(strstr(str, "=") + 1);
381 if (optprn != (int)prn) {
382 trace(NULL, 3, "decode_qzss_l6dmsg: -MIONO_PRN=%d\n", optprn);
383 return -1;
384 }
385 }
386
387 if (si == 1) {
388 _miono[j].maxframe = 0; /* Subframe Indicator : First Data */
389 }
390
391 /* frame recognition */
392 if (_miono[j].maxframe <= 0) {
393 mn = getbitu(mdcl6d->buff, i, 12); /* Message Number(note:not i++) */
394
395 if (mn == MIONO_MT_COV) {
396 corlen = getbitu(mdcl6d->buff, i + 54, 16); /* Length of Correction Messages */
397 narea = getbitu(mdcl6d->buff, i + 70, 5); /* No. of Area */
398 _miono[j].maxframe = (75 + narea * 45 + corlen) / L6_DATA_BITS + 1;
399 trace(NULL, 3, "decode_qzss_l6dmsg: %s,mn=%d,maxframe=%d,corlen=%d,narea=%d\n", time_str(_miono[j].gt, 3),
400 mn, _miono[j].maxframe, corlen, narea);
401 _miono[j].frame = 0;
402 _miono[j].ibuff = 0;
403 } else {
404 trace(NULL, 3, "decode_qzss_l6dmsg: %s,invalid mn=%d\n", time_str(_miono[j].gt, 3), mn);
405 return 0;
406 }
407 }
408
409 /* save data part (1695 bits) */
410 _miono[j].frame++;
411 trace(NULL, 3, "decode_qzss_l6dmsg: %s,maxframe=%d,frame=%d\n", time_str(_miono[j].gt, 3), _miono[j].maxframe,
412 _miono[j].frame);
413 switch (_miono[j].frame % 8) {
414 case 1:
415 ibuff = 0 + _miono[j].frame / 8;
416 n = 8;
417 mask = 0xFE;
418 break;
419 case 2:
420 ibuff = 211 + _miono[j].frame / 8;
421 n = 1;
422 mask = 0xFC;
423 break;
424 case 3:
425 ibuff = 423 + _miono[j].frame / 8;
426 n = 2;
427 mask = 0xF8;
428 break;
429 case 4:
430 ibuff = 635 + _miono[j].frame / 8;
431 n = 3;
432 mask = 0xF0;
433 break;
434 case 5:
435 ibuff = 847 + _miono[j].frame / 8;
436 n = 4;
437 mask = 0xE0;
438 break;
439 case 6:
440 ibuff = 1059 + _miono[j].frame / 8;
441 n = 5;
442 mask = 0xC0;
443 break;
444 case 7:
445 ibuff = 1271 + _miono[j].frame / 8;
446 n = 6;
447 mask = 0x80;
448 break;
449 default:
450 ibuff = 1483 + _miono[j].frame / 8;
451 n = 7;
452 mask = 0xFF;
453 break;
454 }
455 _miono[j].buff[ibuff++] |= (unsigned char)getbitu(mdcl6d->buff, i, n);
456 i += n;
457
458 while (i < L6_HEADER_BITS + L6_DATA_BITS) {
459 _miono[j].buff[ibuff++] = (unsigned char)getbitu(mdcl6d->buff, i, 8);
460 i += 8;
461 }
462 _miono[j].buff[ibuff - 1] &= mask;
463
464 if (_miono[j].frame != _miono[j].maxframe) {
465 return 0; /* no message */
466 }
467
468 ret = 10; /* input MADOCA-PPP iono. messages */
469 i = 0;
470 imax = 0;
471 while (i < L6_DATA_BITS * _miono[j].maxframe) {
472 mn = getbitu(_miono[j].buff, i, 12);
473 i += 12; /* Message Number */
474 i += 4; /* Message Sub Type ID(skip) */
475 if (mn == MIONO_MT_COV) {
476 if (_miono[j].mgfid != (int)mgfid) {
477 trace(NULL, 2, "decode_qzss_l6dmsg: %s,mgfid switched %d -> %d\n", time_str(_miono[j].gt, 3),
478 _miono[j].mgfid, mgfid);
479 _miono[j].mgfid = mgfid;
480 }
481 corlen = getbitu(_miono[j].buff, i + 38, 16); /* Length of Correction Messages */
482 i = decode_miono_coverage(&_miono[j], &mdcl6d->re, i, &imax, &mdcl6d->rid);
483 trace(NULL, 5, "decode_qzss_l6dmsg: i=%d,imax=%d,corlen=%d\n", i, imax, corlen);
484 } else if (mn == MIONO_MT_COR) {
485 apply = 1;
486 /* Note, ref[1] 4.2.1(3) ID 0 and 2 are the same, 1 and 3 are the same. */
487 if ((_miono[j].mgfid & 0x1) != ((int)mgfid & 0x1)) {
488 trace(NULL, 2, "decode_qzss_l6dmsg: %s,mgfid mismatch %d != %d\n", time_str(_miono[j].gt, 3),
489 _miono[j].mgfid, mgfid);
490 apply = 0;
491 }
492 i = decode_miono_correction(&_miono[j], &mdcl6d->re, i, apply);
493 } else {
494 trace(NULL, 2, "decode_qzss_l6dmsg: invalid mn=%d\n", mn);
495 ret = 0;
496 break;
497 }
498 mdcl6d->time = _miono[j].gt;
499 if (i >= imax) {
500 break;
501 }
502 }
503 _miono[j].maxframe = 0;
504 trace(NULL, 4, "decode_qzss_l6dmsg: %s,frames=%d\n", time_str(_miono[j].gt, 3), _miono[j].frame);
505 return ret;
506}
507
508/* initialize MADOCA-PPP wide area ionospheric correction control ------------
509 * initialize MADOCA-PPP wide area ionospheric correction control struct
510 * args : gtime_t gt I GPST for week number determination
511 * return : none
512 *-----------------------------------------------------------------------------*/
513extern void init_miono(const gtime_t gt) {
514 int i;
515
516 for (i = 0; i < MIONO_MAX_PRN; i++) {
517 _miono[i].gt = gt; /* for week number determination */
518 _miono[i].mgfid = -1; /* invalid value */
519 _miono[i].tow0 = -1; /* invalid value */
520 _miono[i].frame = 0; /* initial value */
521 }
522}
523
524/* stack QZSS L6D message ----------------------------------------------------
525 * stack QZSS L6D message and synchronize frame with L6 preamble
526 * args : mdcl6d_t *mdcl6d IO QZSS L6D message control struct
527 * uint8_t data I L6D 1byte data
528 * return : status (-1: error message, 0: no message,
529 * 10: input MADOCA-PPP iono. messages)
530 * note : before calling the function, init_miono()
531 *-----------------------------------------------------------------------------*/
532extern int input_qzssl6d(mdcl6d_t* mdcl6d, const uint8_t data) {
533 trace(NULL, 5, "input_qzssl6d: data=0x%02X,%d\n", data, mdcl6d->nbyte);
534
535 /* synchronize frame with L6 preamble */
536 if ((mdcl6d->nbyte == 0) && (data != 0x1A)) {
537 return 0;
538 } else if (((mdcl6d->nbyte == 1) && (data != 0xCF)) || ((mdcl6d->nbyte == 2) && (data != 0xFC)) ||
539 ((mdcl6d->nbyte == 3) && (data != 0x1D))) {
540 mdcl6d->nbyte = 0;
541 if (data != 0x1A) {
542 return 0;
543 }
544 }
545 mdcl6d->buff[mdcl6d->nbyte++] = data;
546
547 if (mdcl6d->nbyte < L6_FRAME_LEN) {
548 return 0;
549 }
550
551 mdcl6d->nbyte = 0;
553}
554
555/* input QZSS L6D message from file ------------------------------------------
556 * fetch next QZSS L6D message and input a message from file
557 * args : mdcl6d_t *mdcl6d IO QZSS L6D message control struct
558 * FILE *fp I file pointer
559 * return : status (-2: end of file, -1...10: same as input_qzssl6d())
560 * note : same as input_qzssl6d()
561 *-----------------------------------------------------------------------------*/
562extern int input_qzssl6df(mdcl6d_t* mdcl6d, FILE* fp) {
563 int i, data, ret;
564
565 trace(NULL, 4, "input_qzssl6df\n");
566
567 for (i = 0; i < 4096; i++) {
568 if ((data = fgetc(fp)) == EOF) {
569 return -2;
570 }
571 if ((ret = input_qzssl6d(mdcl6d, (uint8_t)data))) {
572 return ret;
573 }
574 }
575 return 0; /* return at every 4k bytes */
576}
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.
MRTKLIB Constants — Physical, navigation, and system constants.
#define SYS_GPS
Definition mrtk_eph.c:65
#define SYS_QZS
Definition mrtk_eph.c:69
#define SYS_CMP
Definition mrtk_eph.c:70
#define SYS_GAL
Definition mrtk_eph.c:68
#define SYS_GLO
Definition mrtk_eph.c:67
#define MIONO_MAX_PRN
const l6_prn_info_t * l6_prn_info(int prn)
Look up the auxiliary information of an L6 PRN.
Definition mrtk_l6.c:74
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
MRTKLIB L6 Module — QZSS L6 frame header parsing.
#define L6_DATA_BITS
Definition mrtk_l6.h:46
#define L6_FRAME_LEN
Definition mrtk_l6.h:43
#define L6_PREAMBLE
Definition mrtk_l6.h:42
#define L6_HEADER_BITS
Definition mrtk_l6.h:45
void satno2id(int sat, char *id)
Definition mrtk_nav.c:817
int satsys(int sat, int *prn)
Definition mrtk_nav.c:117
#define MIONO_SYS_BDS
#define MIONO_MAX_FRAME
#define MIONO_MT_COR
static void adjweek(gtime_t *gt, double tow)
#define MIONO_SYS_GLO
#define MIONO_MT_COV
gtime_t gpst2time(int week, double sec)
Definition mrtk_time.c:165
int satno(int sys, int prn)
Definition mrtk_nav.c:58
void init_miono(const gtime_t gt)
Initialize MADOCA-PPP L6D ionospheric correction control.
static int gnssid2sys(int gnssid)
static int decode_miono_coverage(miono_t *mi, miono_region_t *re, int i, int *imax, int *rid)
#define MIONO_INVALID_12BIT
int decode_qzss_l6dmsg(mdcl6d_t *mdcl6d)
Decode QZSS L6D message.
static int decode_miono_correction(miono_t *mi, miono_region_t *re, int i, int apply)
double timediff(gtime_t t1, gtime_t t2)
Definition mrtk_time.c:279
double time2gpst(gtime_t t, int *week)
Definition mrtk_time.c:181
#define MIONO_INVALID_14BIT
int input_qzssl6d(mdcl6d_t *mdcl6d, const uint8_t data)
Input QZSS L6D message byte-by-byte.
#define MIONO_INVALID_10BIT
int input_qzssl6df(mdcl6d_t *mdcl6d, FILE *fp)
Input QZSS L6D message from file.
char * time_str(gtime_t t, int n)
Definition mrtk_time.c:530
static miono_t _miono[MIONO_MAX_PRN]
#define MIONO_SYS_GPS
#define MIONO_SYS_GAL
#define MIONO_INVALID_8BIT
#define MIONO_SYS_QZS
gtime_t utc2gpst(gtime_t t)
Definition mrtk_time.c:440
gtime_t timeget(void)
Definition mrtk_time.c:289
#define MIONO_MAX_SYS
MRTKLIB Navigation Module — Navigation data types and satellite/nav utility functions.
static mdcl6d_t mdcl6d[MIONO_MAX_PRN]
MRTKLIB Precise Point Positioning (PPP) Module.
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.
GNSS time representation.
Definition mrtk_time.h:49
time_t time
Definition mrtk_time.h:50
Decoded L6 frame header. Raw bit fields; no service-specific remapping.
Definition mrtk_l6.h:68
uint8_t prn
Definition mrtk_l6.h:70
uint8_t anme
Definition mrtk_l6.h:76
uint8_t alert
Definition mrtk_l6.h:78
uint8_t csid
Definition mrtk_l6.h:75
uint8_t msgid
Definition mrtk_l6.h:71
uint8_t fac
Definition mrtk_l6.h:73
uint8_t vid
Definition mrtk_l6.h:72
uint32_t preamble
Definition mrtk_l6.h:69
uint8_t sf_ind
Definition mrtk_l6.h:77
Auxiliary per-PRN information for one L6 PRN.
Definition mrtk_l6.h:92
int8_t iono_slot
Definition mrtk_l6.h:97
QZSS L6D message control struct.
Definition mrtk_ppp.h:50
double span[2]
Definition mrtk_nav.h:226
miono_sat_t sat[MAXSAT]
Definition mrtk_nav.h:227
double ref[2]
Definition mrtk_nav.h:225
miono_area_t area[MIONO_MAX_ANUM]
Definition mrtk_nav.h:234
gtime_t t0
Definition mrtk_nav.h:216
double coef[6]
Definition mrtk_nav.h:218
uint8_t buff[L6_FRAME_LEN *40]