MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_rcv_nvs.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_rcv_nvs.c : NVS receiver raw data decoder
3 *
4 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
5 * Copyright (C) 2023-2025 Cabinet Office, Japan
6 * Copyright (C) 2024-2025 Lighthouse Technology & Consulting Co. Ltd.
7 * Copyright (C) 2023-2025 Japan Aerospace Exploration Agency
8 * Copyright (C) 2023-2025 TOSHIBA ELECTRONIC TECHNOLOGIES CORPORATION
9 * Copyright (C) 2015- Mitsubishi Electric Corp.
10 * Copyright (C) 2014 Geospatial Information Authority of Japan
11 * Copyright (C) 2014 T.SUZUKI
12 * Copyright (C) 2007-2023 T.TAKASU
13 *
14 * SPDX-License-Identifier: BSD-2-Clause
15 *----------------------------------------------------------------------------*/
16#include <ctype.h>
17#include <math.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "mrtklib/mrtk_bits.h"
23#include "mrtklib/mrtk_eph.h"
24#include "mrtklib/mrtk_mat.h"
25#include "mrtklib/mrtk_nav.h"
26#include "mrtklib/mrtk_obs.h"
27#include "mrtklib/mrtk_rcvraw.h"
28#include "mrtklib/mrtk_rtcm.h"
29#include "mrtklib/mrtk_sbas.h"
30#include "mrtklib/mrtk_sys.h"
31#include "mrtklib/mrtk_time.h"
32#include "mrtklib/mrtk_trace.h"
33
34/* Local constants (duplicated from rtklib.h to avoid dependency) */
35#define PI 3.1415926535897932 /* pi */
36#define D2R (PI / 180.0) /* deg to rad */
37#define R2D (180.0 / PI) /* rad to deg */
38#define CLIGHT 299792458.0 /* speed of light (m/s) */
39#define SC2RAD 3.1415926535898 /* semi-circle to radian (IS-GPS) */
40
41#define SYS_NONE 0x00
42#define SYS_GPS 0x01
43#define SYS_SBS 0x02
44#define SYS_GLO 0x04
45#define SYS_GAL 0x08
46#define SYS_QZS 0x10
47#define SYS_CMP 0x20
48#define SYS_IRN 0x40
49
50#define TSYS_GPS 0
51#define TSYS_UTC 1
52#define TSYS_GLO 2
53#define TSYS_GAL 3
54#define TSYS_QZS 4
55#define TSYS_CMP 5
56#define TSYS_IRN 6
57
58#define FREQ1 1.57542E9 /* L1/E1/B1C frequency (Hz) */
59#define FREQ2 1.22760E9 /* L2 frequency (Hz) */
60#define FREQ5 1.17645E9 /* L5/E5a/B2a frequency (Hz) */
61#define FREQ6 1.27875E9 /* E6/L6 frequency (Hz) */
62#define FREQ7 1.20714E9 /* E5b/B2I frequency (Hz) */
63#define FREQ8 1.191795E9 /* E5ab/B2ab frequency (Hz) */
64#define FREQ9 2.492028E9 /* S frequency (Hz) */
65#define FREQ1_GLO 1.60200E9 /* GLONASS G1 base frequency (Hz) */
66#define DFRQ1_GLO 0.56250E6 /* GLONASS G1 bias frequency (Hz/n) */
67#define FREQ2_GLO 1.24600E9 /* GLONASS G2 base frequency (Hz) */
68#define DFRQ2_GLO 0.43750E6 /* GLONASS G2 bias frequency (Hz/n) */
69#define FREQ3_GLO 1.202025E9 /* GLONASS G3 frequency (Hz) */
70#define FREQ1a_GLO 1.600995E9 /* GLONASS G1a frequency (Hz) */
71#define FREQ2a_GLO 1.248060E9 /* GLONASS G2a frequency (Hz) */
72#define FREQ1_CMP 1.561098E9 /* BDS B1I frequency (Hz) */
73
74#define MINPRNGPS 1
75#define MAXPRNGPS 32
76#define MINPRNSBS 120
77#define MAXPRNSBS 158
78
79/* Power-of-2 constants */
80#define P2_5 0.03125
81#define P2_6 0.015625
82#define P2_11 4.882812500000000E-04
83#define P2_15 3.051757812500000E-05
84#define P2_17 7.629394531250000E-06
85#define P2_19 1.907348632812500E-06
86#define P2_20 9.536743164062500E-07
87#define P2_21 4.768371582031250E-07
88#define P2_23 1.192092895507810E-07
89#define P2_24 5.960464477539063E-08
90#define P2_27 7.450580596923828E-09
91#define P2_29 1.862645149230957E-09
92#define P2_30 9.313225746154785E-10
93#define P2_31 4.656612873077393E-10
94#define P2_32 2.328306436538696E-10
95#define P2_33 1.164153218269348E-10
96#define P2_34 5.820766091346740E-11
97#define P2_35 2.910383045673370E-11
98#define P2_38 3.637978807091710E-12
99#define P2_40 9.094947017729280E-13
100#define P2_43 1.136868377216160E-13
101#define P2_46 1.421085471520200E-14
102#define P2_50 8.881784197001252E-16
103#define P2_55 2.775557561562891E-17
104#define P2_59 1.734723475976810E-18
105
106/* Forward declarations for functions in rtklib (resolved at link time) */
107
108#define NVSSYNC 0x10 /* nvs message sync code 1 */
109#define NVSENDMSG 0x03 /* nvs message sync code 1 */
110#define NVSCFG 0x06 /* nvs message cfg-??? */
111
112#define ID_XF5RAW 0xf5 /* nvs msg id: raw measurement data */
113#define ID_X4AIONO 0x4a /* nvs msg id: gps ionospheric data */
114#define ID_X4BTIME 0x4b /* nvs msg id: GPS/GLONASS/UTC timescale data */
115#define ID_XF7EPH 0xf7 /* nvs msg id: subframe buffer */
116#define ID_XE5BIT 0xe5 /* nvs msg id: bit information */
117
118#define ID_XD7ADVANCED 0xd7 /* */
119#define ID_X02RATEPVT 0x02 /* */
120#define ID_XF4RATERAW 0xf4 /* */
121#define ID_XD7SMOOTH 0xd7 /* */
122#define ID_XD5BIT 0xd5 /* */
123
124/* get fields (little-endian) ------------------------------------------------*/
125#define U1(p) (*((uint8_t*)(p)))
126#define I1(p) (*((int8_t*)(p)))
127static uint16_t U2(uint8_t* p) {
128 uint16_t u;
129 memcpy(&u, p, 2);
130 return u;
131}
132static uint32_t U4(uint8_t* p) {
133 uint32_t u;
134 memcpy(&u, p, 4);
135 return u;
136}
137static int16_t I2(uint8_t* p) {
138 int16_t i;
139 memcpy(&i, p, 2);
140 return i;
141}
142static int32_t I4(uint8_t* p) {
143 int32_t i;
144 memcpy(&i, p, 4);
145 return i;
146}
147static float R4(uint8_t* p) {
148 float r;
149 memcpy(&r, p, 4);
150 return r;
151}
152static double R8(uint8_t* p) {
153 double r;
154 memcpy(&r, p, 8);
155 return r;
156}
157
158/* ura values (ref [3] 20.3.3.3.1.1) -----------------------------------------*/
159static const double ura_eph[] = {2.4, 3.4, 4.85, 6.85, 9.65, 13.65, 24.0, 48.0,
160 96.0, 192.0, 384.0, 768.0, 1536.0, 3072.0, 6144.0, 0.0};
161/* ura value (m) to ura index ------------------------------------------------*/
162static int uraindex(double value) {
163 int i;
164 for (i = 0; i < 15; i++) {
165 if (ura_eph[i] >= value) {
166 break;
167 }
168 }
169 return i;
170}
171/* decode NVS xf5-raw: raw measurement data ----------------------------------*/
172static int decode_xf5raw(raw_t* raw) {
173 gtime_t time;
174 double tadj = 0.0, toff = 0.0, tn;
175 int dTowInt;
176 double dTowUTC, dTowGPS, dTowFrac, L1, P1, D1;
177 double gpsutcTimescale;
178 uint8_t rcvTimeScaleCorr, sys, carrNo;
179 int i, j, prn, sat, n = 0, nsat, week;
180 uint8_t* p = raw->buff + 2;
181 char *q, tstr[32], flag;
182
183 trace(NULL, 4, "decode_xf5raw: len=%d\n", raw->len);
184
185 /* time tag adjustment option (-TADJ) */
186 if ((q = strstr(raw->opt, "-tadj"))) {
187 sscanf(q, "-TADJ=%lf", &tadj);
188 }
189 dTowUTC = R8(p);
190 week = U2(p + 8);
191 gpsutcTimescale = R8(p + 10);
192 /* glonassutcTimescale = R8(p+18); */
193 rcvTimeScaleCorr = I1(p + 26);
194
195 /* check gps week range */
196 if (week >= 4096) {
197 trace(NULL, 2, "nvs xf5raw obs week error: week=%d\n", week);
198 return -1;
199 }
200 week = adjgpsweek(week);
201
202 if ((raw->len - 31) % 30) {
203 /* Message length is not correct: there could be an error in the stream */
204 trace(NULL, 2, "nvs xf5raw len=%d seems not be correct\n", raw->len);
205 return -1;
206 }
207 nsat = (raw->len - 31) / 30;
208
209 dTowGPS = dTowUTC + gpsutcTimescale;
210
211 /* Tweak pseudoranges to allow Rinex to represent the NVS time of measure */
212 dTowInt = 10.0 * floor((dTowGPS / 10.0) + 0.5);
213 dTowFrac = dTowGPS - (double)dTowInt;
214 time = gpst2time(week, dTowInt * 0.001);
215
216 /* time tag adjustment */
217 if (tadj > 0.0) {
218 tn = time2gpst(time, &week) / tadj;
219 toff = (tn - floor(tn + 0.5)) * tadj;
220 time = timeadd(time, -toff);
221 }
222 /* check time tag jump and output warning */
223 if (raw->time.time && fabs(timediff(time, raw->time)) > 86400.0) {
224 time2str(time, tstr, 3);
225 trace(NULL, 2, "nvs xf5raw time tag jump warning: time=%s\n", tstr);
226 }
227 if (fabs(timediff(time, raw->time)) <= 1e-3) {
228 time2str(time, tstr, 3);
229 trace(NULL, 2, "nvs xf5raw time tag duplicated: time=%s\n", tstr);
230 return 0;
231 }
232 for (i = 0, p += 27; (i < nsat) && (n < MAXOBS); i++, p += 30) {
233 raw->obs.data[n].time = time;
234 if (U1(p) == 1) {
235 sys = SYS_GLO;
236 } else if (U1(p) == 2) {
237 sys = SYS_GPS;
238 } else if (U1(p) == 4) {
239 sys = SYS_SBS;
240 } else {
241 sys = SYS_NONE;
242 }
243 prn = U1(p + 1);
244 if (sys == SYS_SBS) {
245 prn += 120; /* Correct this */
246 }
247 if (!(sat = satno(sys, prn))) {
248 trace(NULL, 2, "nvs xf5raw satellite number error: sys=%d prn=%d\n", sys, prn);
249 continue;
250 }
251 carrNo = I1(p + 2);
252 L1 = R8(p + 4);
253 P1 = R8(p + 12);
254 D1 = R8(p + 20);
255
256 /* check range error */
257 if (L1 < -1E10 || L1 > 1E10 || P1 < -1E10 || P1 > 1E10 || D1 < -1E5 || D1 > 1E5) {
258 trace(NULL, 2, "nvs xf5raw obs range error: sat=%2d L1=%12.5e P1=%12.5e D1=%12.5e\n", sat, L1, P1, D1);
259 continue;
260 }
261 raw->obs.data[n].SNR[0] = (uint16_t)(I1(p + 3) / SNR_UNIT + 0.5);
262 if (sys == SYS_GLO) {
263 raw->obs.data[n].L[0] = L1 - toff * (FREQ1_GLO + DFRQ1_GLO * carrNo);
264 } else {
265 raw->obs.data[n].L[0] = L1 - toff * FREQ1;
266 }
267 raw->obs.data[n].P[0] = (P1 - dTowFrac) * CLIGHT * 0.001 - toff * CLIGHT; /* in ms, needs to be converted */
268 raw->obs.data[n].D[0] = (float)D1;
269
270 /* set LLI if meas flag 4 (carrier phase present) off -> on */
271 flag = U1(p + 28);
272 raw->obs.data[n].LLI[0] = (flag & 0x08) && !(raw->halfc[sat - 1][0] & 0x08) ? 1 : 0;
273 raw->halfc[sat - 1][0] = flag;
274
275 raw->obs.data[n].code[0] = CODE_L1C;
276 raw->obs.data[n].sat = sat;
277
278 for (j = 1; j < NFREQ + NEXOBS; j++) {
279 raw->obs.data[n].L[j] = raw->obs.data[n].P[j] = 0.0;
280 raw->obs.data[n].D[j] = 0.0;
281 raw->obs.data[n].SNR[j] = raw->obs.data[n].LLI[j] = 0;
282 raw->obs.data[n].code[j] = CODE_NONE;
283 }
284 n++;
285 }
286 raw->time = time;
287 raw->obs.n = n;
288 return 1;
289}
290/* decode ephemeris ----------------------------------------------------------*/
291static int decode_gpsephem(int sat, raw_t* raw) {
292 eph_t eph = {0};
293 uint8_t* puiTmp = (raw->buff) + 2;
294 uint16_t week;
295 double toc;
296
297 trace(NULL, 4, "decode_ephem: sat=%2d\n", sat);
298
299 eph.crs = R4(&puiTmp[2]);
300 eph.deln = R4(&puiTmp[6]) * 1e+3;
301 eph.M0 = R8(&puiTmp[10]);
302 eph.cuc = R4(&puiTmp[18]);
303 eph.e = R8(&puiTmp[22]);
304 eph.cus = R4(&puiTmp[30]);
305 eph.A = pow(R8(&puiTmp[34]), 2);
306 eph.toes = R8(&puiTmp[42]) * 1e-3;
307 eph.cic = R4(&puiTmp[50]);
308 eph.OMG0 = R8(&puiTmp[54]);
309 eph.cis = R4(&puiTmp[62]);
310 eph.i0 = R8(&puiTmp[66]);
311 eph.crc = R4(&puiTmp[74]);
312 eph.omg = R8(&puiTmp[78]);
313 eph.OMGd = R8(&puiTmp[86]) * 1e+3;
314 eph.idot = R8(&puiTmp[94]) * 1e+3;
315 eph.tgd[0] = R4(&puiTmp[102]) * 1e-3;
316 toc = R8(&puiTmp[106]) * 1e-3;
317 eph.f2 = R4(&puiTmp[114]) * 1e+3;
318 eph.f1 = R4(&puiTmp[118]);
319 eph.f0 = R4(&puiTmp[122]) * 1e-3;
320 eph.sva = uraindex(I2(&puiTmp[126]));
321 eph.iode = I2(&puiTmp[128]);
322 eph.iodc = I2(&puiTmp[130]);
323 eph.code = I2(&puiTmp[132]);
324 eph.flag = I2(&puiTmp[134]);
325 week = I2(&puiTmp[136]);
326 eph.fit = 0;
327
328 if (week >= 4096) {
329 trace(NULL, 2, "nvs gps ephemeris week error: sat=%2d week=%d\n", sat, week);
330 return -1;
331 }
332 eph.week = adjgpsweek(week);
333 eph.toe = gpst2time(eph.week, eph.toes);
334 eph.toc = gpst2time(eph.week, toc);
335 eph.ttr = raw->time;
336
337 if (!strstr(raw->opt, "-EPHALL")) {
338 if (eph.iode == raw->nav.eph[sat - 1].iode) {
339 return 0; /* unchanged */
340 }
341 }
342 eph.sat = sat;
343 eph.type = 0; /* ephemeris type = LNAV */
344 raw->nav.eph[sat - 1] = eph;
345 raw->ephsat = sat;
346 raw->ephset = 0;
347 return 2;
348}
349/* adjust daily rollover of time ---------------------------------------------*/
350static gtime_t adjday(gtime_t time, double tod) {
351 double ep[6], tod_p;
352 time2epoch(time, ep);
353 tod_p = ep[3] * 3600.0 + ep[4] * 60.0 + ep[5];
354 if (tod < tod_p - 43200.0) {
355 tod += 86400.0;
356 } else if (tod > tod_p + 43200.0) {
357 tod -= 86400.0;
358 }
359 ep[3] = ep[4] = ep[5] = 0.0;
360 return timeadd(epoch2time(ep), tod);
361}
362/* decode gloephem -----------------------------------------------------------*/
363static int decode_gloephem(int sat, raw_t* raw) {
364 geph_t geph = {0};
365 uint8_t* p = (raw->buff) + 2;
366 int prn, tk, tb;
367
368 if (raw->len >= 93) {
369 prn = I1(p + 1);
370 geph.frq = I1(p + 2);
371 geph.pos[0] = R8(p + 3);
372 geph.pos[1] = R8(p + 11);
373 geph.pos[2] = R8(p + 19);
374 geph.vel[0] = R8(p + 27) * 1e+3;
375 geph.vel[1] = R8(p + 35) * 1e+3;
376 geph.vel[2] = R8(p + 43) * 1e+3;
377 geph.acc[0] = R8(p + 51) * 1e+6;
378 geph.acc[1] = R8(p + 59) * 1e+6;
379 geph.acc[2] = R8(p + 67) * 1e+6;
380 tb = R8(p + 75) * 1e-3;
381 tk = tb;
382 geph.gamn = R4(p + 83);
383 geph.taun = R4(p + 87) * 1e-3;
384 geph.age = I2(p + 91);
385 } else {
386 trace(NULL, 2, "nvs NE length error: len=%d\n", raw->len);
387 return -1;
388 }
389 if (!(geph.sat = satno(SYS_GLO, prn))) {
390 trace(NULL, 2, "nvs NE satellite error: prn=%d\n", prn);
391 return -1;
392 }
393 if (raw->time.time == 0) {
394 return 0;
395 }
396
397 geph.iode = (tb / 900) & 0x7F;
398 geph.toe = utc2gpst(adjday(raw->time, tb - 10800.0));
399 geph.tof = utc2gpst(adjday(raw->time, tk - 10800.0));
400#if 0
401 /* check illegal ephemeris by toe */
402 tt=timediff(raw->time,geph.toe);
403 if (fabs(tt)>3600.0) {
404 trace(NULL,3,"nvs NE illegal toe: prn=%2d tt=%6.0f\n",prn,tt);
405 return 0;
406 }
407#endif
408#if 0
409 /* check illegal ephemeris by frequency number consistency */
410 if (raw->nav.geph[prn-MINPRNGLO].toe.time&&
411 geph.frq!=raw->nav.geph[prn-MINPRNGLO].frq) {
412 trace(NULL,2,"nvs NE illegal freq change: prn=%2d frq=%2d->%2d\n",prn,
413 raw->nav.geph[prn-MINPRNGLO].frq,geph.frq);
414 return -1;
415 }
416 if (!strstr(raw->opt,"-EPHALL")) {
417 if (fabs(timediff(geph.toe,raw->nav.geph[prn-MINPRNGLO].toe))<1.0&&
418 geph.svh==raw->nav.geph[prn-MINPRNGLO].svh) return 0;
419 }
420#endif
421 raw->nav.geph[prn - 1] = geph;
422 raw->ephsat = geph.sat;
423 raw->ephset = 0;
424
425 return 2;
426}
427/* decode NVS ephemerides in clear -------------------------------------------*/
428static int decode_xf7eph(raw_t* raw) {
429 int prn, sat, sys;
430 uint8_t* p = raw->buff;
431
432 trace(NULL, 4, "decode_xf7eph: len=%d\n", raw->len);
433
434 if ((raw->len) < 93) {
435 trace(NULL, 2, "nvs xf7eph length error: len=%d\n", raw->len);
436 return -1;
437 }
438 sys = (U1(p + 2) == 1) ? SYS_GPS : ((U1(p + 2) == 2) ? SYS_GLO : SYS_NONE);
439 prn = U1(p + 3);
440 if (!(sat = satno(sys == 1 ? SYS_GPS : SYS_GLO, prn))) {
441 trace(NULL, 2, "nvs xf7eph satellite number error: prn=%d\n", prn);
442 return -1;
443 }
444 if (sys == SYS_GPS) {
445 return decode_gpsephem(sat, raw);
446 } else if (sys == SYS_GLO) {
447 return decode_gloephem(sat, raw);
448 }
449 return 0;
450}
451/* decode NVS rxm-sfrb: subframe buffer --------------------------------------*/
452static int decode_xe5bit(raw_t* raw) {
453 int prn;
454 int iBlkStartIdx, iExpLen, iIdx;
455 uint32_t words[10];
456 uint8_t uiDataBlocks, uiDataType;
457 uint8_t* p = raw->buff;
458
459 trace(NULL, 4, "decode_xe5bit: len=%d\n", raw->len);
460
461 p += 2; /* Discard preamble and message identifier */
462 uiDataBlocks = U1(p);
463
464 if (uiDataBlocks >= 16) {
465 trace(NULL, 2, "nvs xf5bit message error: data blocks %u\n", uiDataBlocks);
466 return -1;
467 }
468 iBlkStartIdx = 1;
469 for (iIdx = 0; iIdx < uiDataBlocks; iIdx++) {
470 iExpLen = (iBlkStartIdx + 10);
471 if ((raw->len) < iExpLen) {
472 trace(NULL, 2, "nvs xf5bit message too short (expected at least %d)\n", iExpLen);
473 return -1;
474 }
475 uiDataType = U1(p + iBlkStartIdx + 1);
476
477 switch (uiDataType) {
478 case 1: /* Glonass */
479 iBlkStartIdx += 19;
480 break;
481 case 2: /* GPS */
482 iBlkStartIdx += 47;
483 break;
484 case 4: /* SBAS */
485 prn = U1(p + (iBlkStartIdx + 2)) + 120;
486
487 /* sat = satno(SYS_SBS, prn); */
488 /* sys = satsys(sat,&prn); */
489 memset(words, 0, 10 * sizeof(uint32_t));
490 for (iIdx = 0, iBlkStartIdx += 7; iIdx < 10; iIdx++, iBlkStartIdx += 4) {
491 words[iIdx] = U4(p + iBlkStartIdx);
492 }
493 words[7] >>= 6;
494 return sbsdecodemsg(raw->time, prn, words, &raw->sbsmsg) ? 3 : 0;
495 default:
496 trace(NULL, 2, "nvs xf5bit SNS type unknown (got %d)\n", uiDataType);
497 return -1;
498 }
499 }
500 return 0;
501}
502/* decode NVS x4aiono --------------------------------------------------------*/
503static int decode_x4aiono(raw_t* raw) {
504 uint8_t* p = raw->buff + 2;
505
506 trace(NULL, 4, "decode_x4aiono: len=%d\n", raw->len);
507
508 raw->nav.ion_gps[0] = R4(p);
509 raw->nav.ion_gps[1] = R4(p + 4);
510 raw->nav.ion_gps[2] = R4(p + 8);
511 raw->nav.ion_gps[3] = R4(p + 12);
512 raw->nav.ion_gps[4] = R4(p + 16);
513 raw->nav.ion_gps[5] = R4(p + 20);
514 raw->nav.ion_gps[6] = R4(p + 24);
515 raw->nav.ion_gps[7] = R4(p + 28);
516
517 return 9;
518}
519/* decode NVS x4btime --------------------------------------------------------*/
520static int decode_x4btime(raw_t* raw) {
521 uint8_t* p = raw->buff + 2;
522
523 trace(NULL, 4, "decode_x4btime: len=%d\n", raw->len);
524
525 raw->nav.utc_gps[1] = R8(p);
526 raw->nav.utc_gps[0] = R8(p + 8);
527 raw->nav.utc_gps[2] = I4(p + 16);
528 raw->nav.utc_gps[3] = I2(p + 20);
529 raw->nav.utc_gps[4] = I1(p + 22);
530
531 return 9;
532}
533/* decode NVS raw message ----------------------------------------------------*/
534static int decode_nvs(raw_t* raw) {
535 int type = U1(raw->buff + 1);
536
537 trace(NULL, 3, "decode_nvs: type=%02x len=%d\n", type, raw->len);
538
539 sprintf(raw->msgtype, "NVS: type=%2d len=%3d", type, raw->len);
540
541 switch (type) {
542 case ID_XF5RAW:
543 return decode_xf5raw(raw);
544 case ID_XF7EPH:
545 return decode_xf7eph(raw);
546 case ID_XE5BIT:
547 return decode_xe5bit(raw);
548 case ID_X4AIONO:
549 return decode_x4aiono(raw);
550 case ID_X4BTIME:
551 return decode_x4btime(raw);
552 default:
553 break;
554 }
555 return 0;
556}
557/* input NVS raw message from stream -------------------------------------------
558 * fetch next NVS raw data and input a message from stream
559 * args : raw_t *raw IO receiver raw data control struct
560 * uint8_t data I stream data (1 byte)
561 * return : status (-1: error message, 0: no message, 1: input observation data,
562 * 2: input ephemeris, 3: input sbas message,
563 * 9: input ion/utc parameter)
564 *
565 * notes : to specify input options, set raw->opt to the following option
566 * strings separated by spaces.
567 *
568 * -EPHALL : input all ephemerides
569 * -TADJ=tint : adjust time tags to multiples of tint (sec)
570 *
571 *-----------------------------------------------------------------------------*/
572extern int input_nvs(raw_t* raw, uint8_t data) {
573 trace(NULL, 5, "input_nvs: data=%02x\n", data);
574
575 /* synchronize frame */
576 if ((raw->nbyte == 0) && (data == NVSSYNC)) {
577 /* Search a 0x10 */
578 raw->buff[0] = data;
579 raw->nbyte = 1;
580 return 0;
581 }
582 if ((raw->nbyte == 1) && (data != NVSSYNC) && (data != NVSENDMSG)) {
583 /* Discard double 0x10 and 0x10 0x03 at beginning of frame */
584 raw->buff[1] = data;
585 raw->nbyte = 2;
586 raw->flag = 0;
587 return 0;
588 }
589 /* This is all done to discard a double 0x10 */
590 if (data == NVSSYNC) {
591 raw->flag = (raw->flag + 1) % 2;
592 }
593 if ((data != NVSSYNC) || (raw->flag)) {
594 /* Store the new byte */
595 raw->buff[(raw->nbyte++)] = data;
596 }
597 /* Detect ending sequence */
598 if ((data == NVSENDMSG) && (raw->flag)) {
599 raw->len = raw->nbyte;
600 raw->nbyte = 0;
601
602 /* Decode NVS raw message */
603 return decode_nvs(raw);
604 }
605 if (raw->nbyte == MAXRAWLEN) {
606 trace(NULL, 2, "nvs message size error: len=%d\n", raw->nbyte);
607 raw->nbyte = 0;
608 return -1;
609 }
610 return 0;
611}
612/* input NVS raw message from file ---------------------------------------------
613 * fetch next NVS raw data and input a message from file
614 * args : raw_t *raw IO receiver raw data control struct
615 * FILE *fp I file pointer
616 * return : status(-2: end of file, -1...9: same as above)
617 *-----------------------------------------------------------------------------*/
618extern int input_nvsf(raw_t* raw, FILE* fp) {
619 int i, data, odd = 0;
620
621 trace(NULL, 4, "input_nvsf:\n");
622
623 /* synchronize frame */
624 for (i = 0;; i++) {
625 if ((data = fgetc(fp)) == EOF) {
626 return -2;
627 }
628
629 /* Search a 0x10 */
630 if (data == NVSSYNC) {
631 /* Store the frame begin */
632 raw->buff[0] = data;
633 if ((data = fgetc(fp)) == EOF) {
634 return -2;
635 }
636
637 /* Discard double 0x10 and 0x10 0x03 */
638 if ((data != NVSSYNC) && (data != NVSENDMSG)) {
639 raw->buff[1] = data;
640 break;
641 }
642 }
643 if (i >= 4096) {
644 return 0;
645 }
646 }
647 raw->nbyte = 2;
648 for (i = 0;; i++) {
649 if ((data = fgetc(fp)) == EOF) {
650 return -2;
651 }
652 if (data == NVSSYNC) {
653 odd = (odd + 1) % 2;
654 }
655 if ((data != NVSSYNC) || odd) {
656 /* Store the new byte */
657 raw->buff[(raw->nbyte++)] = data;
658 }
659 /* Detect ending sequence */
660 if ((data == NVSENDMSG) && odd) {
661 break;
662 }
663 if (i >= 4096) {
664 return 0;
665 }
666 }
667 raw->len = raw->nbyte;
668 if ((raw->len) > MAXRAWLEN) {
669 trace(NULL, 2, "nvs length error: len=%d\n", raw->len);
670 return -1;
671 }
672 /* decode nvs raw message */
673 return decode_nvs(raw);
674}
675/* generate NVS binary message -------------------------------------------------
676 * generate NVS binary message from message string
677 * args : char *msg I message string
678 * "RESTART [arg...]" system reset
679 * "CFG-SERI [arg...]" configure serial port property
680 * "CFG-FMT [arg...]" configure output message format
681 * "CFG-RATE [arg...]" configure binary measurement output rates
682 * uint8_t *buff O binary message
683 * return : length of binary message (0: error)
684 * note : see reference [1][2] for details.
685 *-----------------------------------------------------------------------------*/
686extern int gen_nvs(const char* msg, uint8_t* buff) {
687 uint8_t* q = buff;
688 char mbuff[1024], *args[32], *p;
689 uint32_t byte;
690 int iRate, n, narg = 0;
691 uint8_t ui100Ms;
692
693 trace(NULL, 4, "gen_nvs: msg=%s\n", msg);
694
695 strcpy(mbuff, msg);
696 for (p = strtok(mbuff, " "); p && narg < 32; p = strtok(NULL, " ")) {
697 args[narg++] = p;
698 }
699 if (narg < 1) {
700 return 0;
701 }
702 *q++ = NVSSYNC; /* DLE */
703
704 if (!strcmp(args[0], "CFG-PVTRATE")) {
705 *q++ = ID_XD7ADVANCED;
706 *q++ = ID_X02RATEPVT;
707 if (narg > 1) {
708 iRate = atoi(args[1]);
709 *q++ = (uint8_t)iRate;
710 }
711 } else if (!strcmp(args[0], "CFG-RAWRATE")) {
712 *q++ = ID_XF4RATERAW;
713 if (narg > 1) {
714 iRate = atoi(args[1]);
715 switch (iRate) {
716 case 2:
717 ui100Ms = 5;
718 break;
719 case 5:
720 ui100Ms = 2;
721 break;
722 case 10:
723 ui100Ms = 1;
724 break;
725 default:
726 ui100Ms = 10;
727 break;
728 }
729 *q++ = ui100Ms;
730 }
731 } else if (!strcmp(args[0], "CFG-SMOOTH")) {
732 *q++ = ID_XD7SMOOTH;
733 *q++ = 0x03;
734 *q++ = 0x01;
735 *q++ = 0x00;
736 } else if (!strcmp(args[0], "CFG-BINR")) {
737 for (n = 1; (n < narg); n++) {
738 if (sscanf(args[n], "%2x", &byte)) {
739 *q++ = (uint8_t)byte;
740 }
741 }
742 } else {
743 return 0;
744 }
745
746 n = (int)(q - buff);
747
748 *q++ = 0x10; /* ETX */
749 *q = 0x03; /* DLE */
750 return n + 2;
751}
MRTKLIB Bits Module — Binary bit operations and CRC functions.
#define CLIGHT
Definition mrtk_coords.c:41
#define SYS_GPS
Definition mrtk_eph.c:65
#define SYS_NONE
Definition mrtk_eph.c:64
#define SYS_SBS
Definition mrtk_eph.c:66
#define SYS_GLO
Definition mrtk_eph.c:67
MRTKLIB Broadcast Ephemeris Module — Satellite orbit/clock types and Kepler/GLONASS/SBAS orbit comput...
#define SNR_UNIT
#define MAXOBS
#define CODE_L1C
#define CODE_NONE
#define MAXRAWLEN
#define MINPRNGLO
MRTKLIB Matrix Module — Matrix/vector operations and estimation.
int satno(int sys, int prn)
Convert satellite system+prn/slot number to satellite number.
Definition mrtk_nav.c:58
MRTKLIB Navigation Module — Navigation data types and satellite/nav utility functions.
#define FREQ1
Definition mrtk_obs.c:67
#define FREQ1_GLO
Definition mrtk_obs.c:74
#define DFRQ1_GLO
Definition mrtk_obs.c:75
MRTKLIB Observation Module — Observation data types and utility functions.
#define U1(p)
static int decode_xe5bit(raw_t *raw)
static int uraindex(double value)
#define ID_XF4RATERAW
static gtime_t adjday(gtime_t time, double tod)
#define ID_XD7ADVANCED
#define ID_XD7SMOOTH
#define ID_X4BTIME
static int decode_gloephem(int sat, raw_t *raw)
int input_nvs(raw_t *raw, uint8_t data)
int gen_nvs(const char *msg, uint8_t *buff)
static int decode_nvs(raw_t *raw)
#define ID_XF7EPH
#define NVSSYNC
#define ID_XF5RAW
static int decode_x4aiono(raw_t *raw)
static int decode_xf5raw(raw_t *raw)
int input_nvsf(raw_t *raw, FILE *fp)
#define NVSENDMSG
#define ID_X02RATEPVT
#define ID_X4AIONO
static int decode_gpsephem(int sat, raw_t *raw)
#define I1(p)
static int decode_x4btime(raw_t *raw)
#define ID_XE5BIT
static int decode_xf7eph(raw_t *raw)
#define R8(p)
#define U4(p)
#define I4(p)
#define R4(p)
#define U2(p)
#define I2(p)
MRTKLIB Receiver Raw Data Module — Receiver raw data types and decoder functions for various GNSS rec...
static const double ura_eph[]
Definition mrtk_rinex.c:84
MRTKLIB RTCM Module — RTCM message types and functions.
int sbsdecodemsg(gtime_t time, int prn, const uint32_t *words, sbsmsg_t *sbsmsg)
Decode SBAS message frame words.
Definition mrtk_sbas.c:1080
MRTKLIB SBAS Module — SBAS message decoding and corrections.
MRTKLIB System Module — OS/filesystem utility functions.
gtime_t epoch2time(const double *ep)
Convert calendar day/time to gtime_t struct.
Definition mrtk_time.c:113
gtime_t gpst2time(int week, double sec)
Convert GPS week/tow to gtime_t.
Definition mrtk_time.c:165
void time2epoch(gtime_t t, double *ep)
Convert gtime_t struct to calendar day/time.
Definition mrtk_time.c:136
void time2str(gtime_t t, char *s, int n)
Convert gtime_t struct to string.
Definition mrtk_time.c:507
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 utc2gpst(gtime_t t)
Convert UTC to GPS time considering leap seconds.
Definition mrtk_time.c:440
MRTKLIB Time Module — GNSS time types and conversion functions.
void trace(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message.
Definition mrtk_trace.c:78
MRTKLIB Trace Module — debug trace and logging functions.
GPS/GAL/QZS/BDS/IRN broadcast ephemeris type.
Definition mrtk_eph.h:77
double OMG0
Definition mrtk_eph.h:90
double omg
Definition mrtk_eph.h:90
int sat
Definition mrtk_eph.h:78
gtime_t ttr
Definition mrtk_eph.h:88
double OMGd
Definition mrtk_eph.h:90
double f1
Definition mrtk_eph.h:94
double f0
Definition mrtk_eph.h:94
double e
Definition mrtk_eph.h:90
double idot
Definition mrtk_eph.h:90
double M0
Definition mrtk_eph.h:90
double A
Definition mrtk_eph.h:90
double cis
Definition mrtk_eph.h:91
int flag
Definition mrtk_eph.h:86
gtime_t toe
Definition mrtk_eph.h:88
double fit
Definition mrtk_eph.h:93
int week
Definition mrtk_eph.h:82
gtime_t toc
Definition mrtk_eph.h:88
double cic
Definition mrtk_eph.h:91
double tgd[6]
Definition mrtk_eph.h:95
double cus
Definition mrtk_eph.h:91
double cuc
Definition mrtk_eph.h:91
double toes
Definition mrtk_eph.h:92
int code
Definition mrtk_eph.h:83
int type
Definition mrtk_eph.h:100
double crs
Definition mrtk_eph.h:91
double i0
Definition mrtk_eph.h:90
int iode
Definition mrtk_eph.h:79
int sva
Definition mrtk_eph.h:80
double deln
Definition mrtk_eph.h:90
double crc
Definition mrtk_eph.h:91
double f2
Definition mrtk_eph.h:94
int iodc
Definition mrtk_eph.h:79
GLONASS broadcast ephemeris type.
Definition mrtk_eph.h:111
double vel[3]
Definition mrtk_eph.h:121
gtime_t toe
Definition mrtk_eph.h:118
double pos[3]
Definition mrtk_eph.h:120
int iode
Definition mrtk_eph.h:113
double gamn
Definition mrtk_eph.h:123
double acc[3]
Definition mrtk_eph.h:122
int age
Definition mrtk_eph.h:117
int svh
Definition mrtk_eph.h:115
double taun
Definition mrtk_eph.h:123
gtime_t tof
Definition mrtk_eph.h:119
int sat
Definition mrtk_eph.h:112
int frq
Definition mrtk_eph.h:114
GNSS time representation.
Definition mrtk_time.h:49
time_t time
Definition mrtk_time.h:50
double utc_gps[8]
Definition mrtk_nav.h:414
geph_t * geph
Definition mrtk_nav.h:407
eph_t * eph
Definition mrtk_nav.h:400
double ion_gps[8]
Definition mrtk_nav.h:421
obsd_t * data
Definition mrtk_obs.h:61
int n
Definition mrtk_obs.h:60
float D[5+5]
Definition mrtk_obs.h:52
gtime_t time
Definition mrtk_obs.h:45
uint8_t sat
Definition mrtk_obs.h:46
uint8_t LLI[5+5]
Definition mrtk_obs.h:48
double L[5+5]
Definition mrtk_obs.h:50
double P[5+5]
Definition mrtk_obs.h:51
uint16_t SNR[5+5]
Definition mrtk_obs.h:47
uint8_t code[5+5]
Definition mrtk_obs.h:49
Receiver raw data control type.
Definition mrtk_rcvraw.h:78
sbsmsg_t sbsmsg
Definition mrtk_rcvraw.h:87
nav_t nav
Definition mrtk_rcvraw.h:83
int ephset
Definition mrtk_rcvraw.h:86
obs_t obs
Definition mrtk_rcvraw.h:81
int len
Definition mrtk_rcvraw.h:96
uint8_t buff[MAXRAWLEN]
char msgtype[256]
Definition mrtk_rcvraw.h:88
int nbyte
Definition mrtk_rcvraw.h:95
int flag
uint8_t halfc[MAXSAT][5+5]
Definition mrtk_rcvraw.h:93
char opt[256]
int ephsat
Definition mrtk_rcvraw.h:85
gtime_t time
Definition mrtk_rcvraw.h:79