MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_rcv_crescent.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_rcv_crescent.c : Hemisphere (Crescent) 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_sys.h"
30#include "mrtklib/mrtk_time.h"
31#include "mrtklib/mrtk_trace.h"
32
33/* Local constants (duplicated from rtklib.h to avoid dependency) */
34#define PI 3.1415926535897932 /* pi */
35#define D2R (PI / 180.0) /* deg to rad */
36#define R2D (180.0 / PI) /* rad to deg */
37#define CLIGHT 299792458.0 /* speed of light (m/s) */
38#define SC2RAD 3.1415926535898 /* semi-circle to radian (IS-GPS) */
39
40#define SYS_NONE 0x00
41#define SYS_GPS 0x01
42#define SYS_SBS 0x02
43#define SYS_GLO 0x04
44#define SYS_GAL 0x08
45#define SYS_QZS 0x10
46#define SYS_CMP 0x20
47#define SYS_IRN 0x40
48
49#define TSYS_GPS 0
50#define TSYS_UTC 1
51#define TSYS_GLO 2
52#define TSYS_GAL 3
53#define TSYS_QZS 4
54#define TSYS_CMP 5
55#define TSYS_IRN 6
56
57#define FREQ1 1.57542E9 /* L1/E1/B1C frequency (Hz) */
58#define FREQ2 1.22760E9 /* L2 frequency (Hz) */
59#define FREQ5 1.17645E9 /* L5/E5a/B2a frequency (Hz) */
60#define FREQ6 1.27875E9 /* E6/L6 frequency (Hz) */
61#define FREQ7 1.20714E9 /* E5b/B2I frequency (Hz) */
62#define FREQ8 1.191795E9 /* E5ab/B2ab frequency (Hz) */
63#define FREQ9 2.492028E9 /* S frequency (Hz) */
64#define FREQ1_GLO 1.60200E9 /* GLONASS G1 base frequency (Hz) */
65#define DFRQ1_GLO 0.56250E6 /* GLONASS G1 bias frequency (Hz/n) */
66#define FREQ2_GLO 1.24600E9 /* GLONASS G2 base frequency (Hz) */
67#define DFRQ2_GLO 0.43750E6 /* GLONASS G2 bias frequency (Hz/n) */
68#define FREQ3_GLO 1.202025E9 /* GLONASS G3 frequency (Hz) */
69#define FREQ1a_GLO 1.600995E9 /* GLONASS G1a frequency (Hz) */
70#define FREQ2a_GLO 1.248060E9 /* GLONASS G2a frequency (Hz) */
71#define FREQ1_CMP 1.561098E9 /* BDS B1I frequency (Hz) */
72
73#define MINPRNGPS 1
74#define MAXPRNGPS 32
75#define MINPRNSBS 120
76#define MAXPRNSBS 158
77
78/* Power-of-2 constants */
79#define P2_5 0.03125
80#define P2_6 0.015625
81#define P2_11 4.882812500000000E-04
82#define P2_15 3.051757812500000E-05
83#define P2_17 7.629394531250000E-06
84#define P2_19 1.907348632812500E-06
85#define P2_20 9.536743164062500E-07
86#define P2_21 4.768371582031250E-07
87#define P2_23 1.192092895507810E-07
88#define P2_24 5.960464477539063E-08
89#define P2_27 7.450580596923828E-09
90#define P2_29 1.862645149230957E-09
91#define P2_30 9.313225746154785E-10
92#define P2_31 4.656612873077393E-10
93#define P2_32 2.328306436538696E-10
94#define P2_33 1.164153218269348E-10
95#define P2_34 5.820766091346740E-11
96#define P2_35 2.910383045673370E-11
97#define P2_38 3.637978807091710E-12
98#define P2_40 9.094947017729280E-13
99#define P2_43 1.136868377216160E-13
100#define P2_46 1.421085471520200E-14
101#define P2_50 8.881784197001252E-16
102#define P2_55 2.775557561562891E-17
103#define P2_59 1.734723475976810E-18
104
105/* Forward declarations for functions in rtklib (resolved at link time) */
106
107#define CRESSYNC "$BIN" /* hemis bin sync code */
108
109#define ID_CRESPOS 1 /* hemis msg id: bin 1 position/velocity */
110#define ID_CRESGLOEPH 65 /* hemis msg id: bin 65 glonass ephemeris */
111#define ID_CRESGLORAW 66 /* hemis msg id: bin 66 glonass L1/L2 phase and code */
112#define ID_CRESRAW2 76 /* hemis msg id: bin 76 dual-freq raw */
113#define ID_CRESWAAS 80 /* hemis msg id: bin 80 waas messages */
114#define ID_CRESIONUTC 94 /* hemis msg id: bin 94 ion/utc parameters */
115#define ID_CRESEPH 95 /* hemis msg id: bin 95 raw ephemeris */
116#define ID_CRESRAW 96 /* hemis msg id: bin 96 raw phase and code */
117
118#define SNR2CN0_L1 30.0 /* hemis snr to c/n0 offset (db) L1 */
119#define SNR2CN0_L2 30.0 /* hemis snr to c/n0 offset (db) L2 */
120
121/* get fields (little-endian) ------------------------------------------------*/
122#define U1(p) (*((uint8_t*)(p)))
123#define I1(p) (*((int8_t*)(p)))
124static uint16_t U2(uint8_t* p) {
125 uint16_t u;
126 memcpy(&u, p, 2);
127 return u;
128}
129static uint32_t U4(uint8_t* p) {
130 uint32_t u;
131 memcpy(&u, p, 4);
132 return u;
133}
134static int16_t I2(uint8_t* p) {
135 int16_t i;
136 memcpy(&i, p, 2);
137 return i;
138}
139static int32_t I4(uint8_t* p) {
140 int32_t i;
141 memcpy(&i, p, 4);
142 return i;
143}
144static float R4(uint8_t* p) {
145 float r;
146 memcpy(&r, p, 4);
147 return r;
148}
149static double R8(uint8_t* p) {
150 double r;
151 memcpy(&r, p, 8);
152 return r;
153}
154
155/* checksum ------------------------------------------------------------------*/
156static int chksum(const uint8_t* buff, int len) {
157 uint16_t sum = 0;
158 int i;
159
160 for (i = 8; i < len - 4; i++) {
161 sum += buff[i];
162 }
163 trace(NULL, 4, "checksum=%02X%02X %02X%02X:%02X%02X\n", sum >> 8, sum & 0xFF, buff[len - 3], buff[len - 4],
164 buff[len - 2], buff[len - 1]);
165 return (sum >> 8) == buff[len - 3] && (sum & 0xFF) == buff[len - 4] && buff[len - 2] == 0x0D &&
166 buff[len - 1] == 0x0A;
167}
168/* decode bin 1 position/velocity --------------------------------------------*/
169static int decode_crespos(raw_t* raw) {
170 int ns, week, mode;
171 double tow, pos[3], vel[3], std;
172 char tstr[64];
173 uint8_t* p = raw->buff + 8;
174
175 trace(NULL, 4, "decode_crespos: len=%d\n", raw->len);
176
177 if (raw->len != 64) {
178 trace(NULL, 2, "crescent bin 1 message length error: len=%d\n", raw->len);
179 return -1;
180 }
181 ns = U1(p + 1);
182 week = U2(p + 2);
183 tow = R8(p + 4);
184 pos[0] = R8(p + 12);
185 pos[1] = R8(p + 20);
186 pos[2] = R4(p + 28);
187 vel[0] = R4(p + 32);
188 vel[1] = R4(p + 36);
189 vel[2] = R4(p + 40);
190 std = R4(p + 44);
191 mode = U2(p + 48);
192 time2str(gpst2time(week, tow), tstr, 3);
193 int mode_val;
194 if (mode == 6) {
195 mode_val = 1;
196 } else if (mode > 4) {
197 mode_val = 2;
198 } else if (mode > 1) {
199 mode_val = 5;
200 } else {
201 mode_val = 0;
202 }
203 trace(NULL, 3, "$BIN1 %s %13.9f %14.9f %10.4f %4d %3d %.3f\n", tstr, pos[0], pos[1], pos[2], mode_val, ns, std);
204 return 0;
205}
206/* decode bin 96 raw phase and code ------------------------------------------*/
207static int decode_cresraw(raw_t* raw) {
208 gtime_t time;
209 double tow, tows, toff = 0.0, cp, pr, dop, snr, freq = FREQ1;
210 int i, j, n, prn, sat, week, word2, lli = 0;
211 uint32_t word1, sn, sc;
212 uint8_t* p = raw->buff + 8;
213
214 trace(NULL, 4, "decode_cresraw: len=%d\n", raw->len);
215
216 if (raw->len != 312) {
217 trace(NULL, 2, "crescent bin 96 message length error: len=%d\n", raw->len);
218 return -1;
219 }
220 week = U2(p + 2);
221 tow = R8(p + 4);
222 tows = floor(tow * 1000.0 + 0.5) / 1000.0; /* round by 1ms */
223 time = gpst2time(week, tows);
224
225 /* time tag offset correction */
226 if (strstr(raw->opt, "-TTCORR")) {
227 toff = CLIGHT * (tows - tow);
228 }
229 for (i = n = 0, p += 12; i < 12 && n < MAXOBS; i++, p += 24) {
230 word1 = U4(p);
231 word2 = I4(p + 4);
232 if ((prn = word1 & 0xFF) == 0) {
233 continue; /* if 0, no data */
234 }
235 if (!(sat = satno(prn <= MAXPRNGPS ? SYS_GPS : SYS_SBS, prn))) {
236 trace(NULL, 2, "creasent bin 96 satellite number error: prn=%d\n", prn);
237 continue;
238 }
239 pr = R8(p + 8) - toff;
240 cp = R8(p + 16) - toff;
241 if (!(word2 & 1)) {
242 cp = 0.0; /* invalid phase */
243 }
244 sn = (word1 >> 8) & 0xFF;
245 snr = sn == 0 ? 0.0 : 10.0 * log10(0.8192 * sn) + SNR2CN0_L1;
246 sc = (uint32_t)(word1 >> 24);
247 if (raw->time.time != 0) {
248 lli = (int)((uint8_t)sc - (uint8_t)raw->lockt[sat - 1][0]) > 0;
249 }
250 raw->lockt[sat - 1][0] = (uint8_t)sc;
251 dop = word2 / 16 / 4096.0;
252
253 raw->obs.data[n].time = time;
254 raw->obs.data[n].sat = sat;
255 raw->obs.data[n].P[0] = pr;
256 raw->obs.data[n].L[0] = cp * freq / CLIGHT;
257 raw->obs.data[n].D[0] = -(float)(dop * freq / CLIGHT);
258 raw->obs.data[n].SNR[0] = (uint16_t)(snr / SNR_UNIT + 0.5);
259 raw->obs.data[n].LLI[0] = (uint8_t)lli;
260 raw->obs.data[n].code[0] = CODE_L1C;
261
262 for (j = 1; j < NFREQ; j++) {
263 raw->obs.data[n].L[j] = raw->obs.data[n].P[j] = 0.0;
264 raw->obs.data[n].D[j] = 0.0;
265 raw->obs.data[n].SNR[j] = raw->obs.data[n].LLI[j] = 0;
266 raw->obs.data[n].code[j] = CODE_NONE;
267 }
268 n++;
269 }
270 raw->time = time;
271 raw->obs.n = n;
272 return 1;
273}
274/* decode bin 76 dual-freq raw phase and code --------------------------------*/
275static int decode_cresraw2(raw_t* raw) {
276 gtime_t time;
277 double tow, tows, toff = 0.0, cp[2] = {0}, pr1, pr[2] = {0}, dop[2] = {0}, snr[2] = {0};
278 double freq[2] = {FREQ1, FREQ2};
279 int i, j, n = 0, prn, sat, week, lli[2] = {0};
280 uint32_t word1, word2, word3, sc, sn;
281 uint8_t* p = raw->buff + 8;
282
283 trace(NULL, 4, "decode_cresraw2: len=%d\n", raw->len);
284
285 if (raw->len != 460) {
286 trace(NULL, 2, "crescent bin 76 message length error: len=%d\n", raw->len);
287 return -1;
288 }
289 tow = R8(p);
290 week = U2(p + 8);
291 tows = floor(tow * 1000.0 + 0.5) / 1000.0; /* round by 1ms */
292 time = gpst2time(week, tows);
293
294 /* time tag offset correction */
295 if (strstr(raw->opt, "-TTCORR")) {
296 toff = CLIGHT * (tows - tow);
297 }
298 if (fabs(timediff(time, raw->time)) < 1e-9) {
299 n = raw->obs.n;
300 }
301 for (i = 0, p += 16; i < 15 && n < MAXOBS; i++) {
302 word1 = U4(p + 324 + 4 * i); /* L1CACodeMSBsPRN */
303 if ((prn = word1 & 0xFF) == 0) {
304 continue; /* if 0, no data */
305 }
306 if (!(sat = satno(prn <= MAXPRNGPS ? SYS_GPS : SYS_SBS, prn))) {
307 trace(NULL, 2, "creasent bin 76 satellite number error: prn=%d\n", prn);
308 continue;
309 }
310 pr1 = (word1 >> 13) * 256.0; /* upper 19bit of L1CA pseudorange */
311
312 word1 = U4(p + 144 + 12 * i); /* L1CASatObs */
313 word2 = U4(p + 148 + 12 * i);
314 word3 = U4(p + 152 + 12 * i);
315 sn = word1 & 0xFFF;
316 snr[0] = sn == 0 ? 0.0 : 10.0 * log10(0.1024 * sn) + SNR2CN0_L1;
317 sc = (uint32_t)(word1 >> 24);
318 if (raw->time.time != 0) {
319 lli[0] = (int)((uint8_t)sc - (uint8_t)raw->lockt[sat - 1][0]) > 0;
320 } else {
321 lli[0] = 0;
322 }
323 lli[0] |= ((word1 >> 12) & 7) ? 2 : 0;
324 raw->lockt[sat - 1][0] = (uint8_t)sc;
325 dop[0] = ((word2 >> 1) & 0x7FFFFF) / 512.0;
326 if ((word2 >> 24) & 1) {
327 dop[0] = -dop[0];
328 }
329 pr[0] = pr1 + (word3 & 0xFFFF) / 256.0;
330 cp[0] = floor(pr[0] * freq[0] / CLIGHT / 8192.0) * 8192.0;
331 cp[0] += ((word2 & 0xFE000000) + ((word3 & 0xFFFF0000) >> 7)) / 524288.0;
332 if (cp[0] - pr[0] * freq[0] / CLIGHT < -4096.0) {
333 cp[0] += 8192.0;
334 } else if (cp[0] - pr[0] * freq[0] / CLIGHT > 4096.0) {
335 cp[0] -= 8192.0;
336 }
337
338 if (i < 12) {
339 word1 = U4(p + 12 * i); /* L2PSatObs */
340 word2 = U4(p + 4 + 12 * i);
341 word3 = U4(p + 8 + 12 * i);
342 sn = word1 & 0xFFF;
343 snr[1] = sn == 0 ? 0.0 : 10.0 * log10(0.1164 * sn) + SNR2CN0_L2;
344 sc = (uint32_t)(word1 >> 24);
345 if (raw->time.time == 0) {
346 lli[1] = (int)((uint8_t)sc - (uint8_t)raw->lockt[sat - 1][1]) > 0;
347 } else {
348 lli[1] = 0;
349 }
350 lli[1] |= ((word1 >> 12) & 7) ? 2 : 0;
351 raw->lockt[sat - 1][1] = (uint8_t)sc;
352 dop[1] = ((word2 >> 1) & 0x7FFFFF) / 512.0;
353 if ((word2 >> 24) & 1) {
354 dop[1] = -dop[1];
355 }
356 pr[1] = (word3 & 0xFFFF) / 256.0;
357 if (pr[1] != 0.0) {
358 pr[1] += pr1;
359 if (pr[1] - pr[0] < -128.0) {
360 pr[1] += 256.0;
361 } else if (pr[1] - pr[0] > 128.0) {
362 pr[1] -= 256.0;
363 }
364 cp[1] = floor(pr[1] * freq[1] / CLIGHT / 8192.0) * 8192.0;
365 cp[1] += ((word2 & 0xFE000000) + ((word3 & 0xFFFF0000) >> 7)) / 524288.0;
366 if (cp[1] - pr[1] * freq[1] / CLIGHT < -4096.0) {
367 cp[1] += 8192.0;
368 } else if (cp[1] - pr[1] * freq[1] / CLIGHT > 4096.0) {
369 cp[1] -= 8192.0;
370 }
371 } else {
372 cp[1] = 0.0;
373 }
374 }
375 raw->obs.data[n].time = time;
376 raw->obs.data[n].sat = sat;
377 for (j = 0; j < NFREQ; j++) {
378 if (j == 0 || (j == 1 && i < 12)) {
379 raw->obs.data[n].P[j] = pr[j] == 0.0 ? 0.0 : pr[j] - toff;
380 raw->obs.data[n].L[j] = cp[j] == 0.0 ? 0.0 : cp[j] - toff * freq[j] / CLIGHT;
381 raw->obs.data[n].D[j] = -(float)dop[j];
382 raw->obs.data[n].SNR[j] = (uint16_t)(snr[j] / SNR_UNIT + 0.5);
383 raw->obs.data[n].LLI[j] = (uint8_t)lli[j];
384 raw->obs.data[n].code[j] = j == 0 ? CODE_L1C : CODE_L2P;
385 } else {
386 raw->obs.data[n].L[j] = raw->obs.data[n].P[j] = 0.0;
387 raw->obs.data[n].D[j] = 0.0;
388 raw->obs.data[n].SNR[j] = raw->obs.data[n].LLI[j] = 0;
389 raw->obs.data[n].code[j] = CODE_NONE;
390 }
391 }
392 n++;
393 }
394 raw->time = time;
395 raw->obs.n = n;
396 if (strstr(raw->opt, "-ENAGLO")) {
397 return 0; /* glonass follows */
398 }
399 return 1;
400}
401/* decode bin 95 ephemeris ---------------------------------------------------*/
402static int decode_creseph(raw_t* raw) {
403 eph_t eph = {0};
404 uint32_t word;
405 int i, j, k, prn, sat;
406 uint8_t *p = raw->buff + 8, buff[90];
407
408 trace(NULL, 4, "decode_creseph: len=%d\n", raw->len);
409
410 if (raw->len != 140) {
411 trace(NULL, 2, "crescent bin 95 message length error: len=%d\n", raw->len);
412 return -1;
413 }
414 prn = U2(p);
415 if (!(sat = satno(SYS_GPS, prn))) {
416 trace(NULL, 2, "crescent bin 95 satellite number error: prn=%d\n", prn);
417 return -1;
418 }
419 for (i = 0; i < 3; i++) {
420 for (j = 0; j < 10; j++) {
421 word = U4(p + 8 + i * 40 + j * 4) >> 6;
422 for (k = 0; k < 3; k++) {
423 buff[i * 30 + j * 3 + k] = (uint8_t)((word >> (8 * (2 - k))) & 0xFF);
424 }
425 }
426 }
427 if (!decode_frame(buff, &eph, NULL, NULL, NULL)) {
428 trace(NULL, 2, "crescent bin 95 navigation frame error: prn=%d\n", prn);
429 return -1;
430 }
431 if (!strstr(raw->opt, "-EPHALL")) {
432 if (eph.iode == raw->nav.eph[sat - 1].iode) {
433 return 0; /* unchanged */
434 }
435 }
436 eph.sat = sat;
437 raw->nav.eph[sat - 1] = eph;
438 raw->ephsat = sat;
439 raw->ephset = 0;
440 return 2;
441}
442/* decode bin 94 ion/utc parameters ------------------------------------------*/
443static int decode_cresionutc(raw_t* raw) {
444 int i;
445 uint8_t* p = raw->buff + 8;
446
447 trace(NULL, 4, "decode_cresionutc: len=%d\n", raw->len);
448
449 if (raw->len != 108) {
450 trace(NULL, 2, "crescent bin 94 message length error: len=%d\n", raw->len);
451 return -1;
452 }
453 for (i = 0; i < 8; i++) {
454 raw->nav.ion_gps[i] = R8(p + i * 8);
455 }
456 raw->nav.utc_gps[0] = R8(p + 64);
457 raw->nav.utc_gps[1] = R8(p + 72);
458 raw->nav.utc_gps[2] = (double)U4(p + 80);
459 raw->nav.utc_gps[3] = (double)U2(p + 84);
460 raw->nav.utc_gps[4] = I2(p + 90);
461 return 9;
462}
463/* decode bin 80 waas messages -----------------------------------------------*/
464static int decode_creswaas(raw_t* raw) {
465 double tow;
466 uint32_t word;
467 int i, j, k, prn;
468 uint8_t* p = raw->buff + 8;
469
470 trace(NULL, 4, "decode_creswaas: len=%d\n", raw->len);
471
472 if (raw->len != 52) {
473 trace(NULL, 2, "creasent bin 80 message length error: len=%d\n", raw->len);
474 return -1;
475 }
476 prn = U2(p);
477 if (prn < MINPRNSBS || MAXPRNSBS < prn) {
478 trace(NULL, 2, "creasent bin 80 satellite number error: prn=%d\n", prn);
479 return -1;
480 }
481 raw->sbsmsg.prn = prn;
482 raw->sbsmsg.tow = U4(p + 4);
483 tow = time2gpst(raw->time, &raw->sbsmsg.week);
484 if (raw->sbsmsg.tow < tow - 302400.0) {
485 raw->sbsmsg.week++;
486 } else if (raw->sbsmsg.tow > tow + 302400.0) {
487 raw->sbsmsg.week--;
488 }
489
490 for (i = k = 0; i < 8 && k < 29; i++) {
491 word = U4(p + 8 + i * 4);
492 for (j = 0; j < 4 && k < 29; j++) {
493 raw->sbsmsg.msg[k++] = (uint8_t)(word >> (3 - j) * 8);
494 }
495 }
496 raw->sbsmsg.msg[28] &= 0xC0;
497 return 3;
498}
499/* decode bin 66 glonass L1/L2 code and carrier phase ------------------------*/
500static int decode_cresgloraw(raw_t* raw) {
501 gtime_t time;
502 double tow, tows, toff = 0.0, cp[2] = {0}, pr1, pr[2] = {0}, dop[2] = {0}, snr[2] = {0};
503 double freq[2];
504 int i, j, n = 0, prn, sat, week, lli[2] = {0};
505 uint32_t word1, word2, word3, sc, sn;
506 uint8_t* p = raw->buff + 8;
507
508 trace(NULL, 4, "decode_cregloraw: len=%d\n", raw->len);
509
510 if (!strstr(raw->opt, "-ENAGLO")) {
511 return 0;
512 }
513
514 if (raw->len != 364) {
515 trace(NULL, 2, "crescent bin 66 message length error: len=%d\n", raw->len);
516 return -1;
517 }
518 tow = R8(p);
519 week = U2(p + 8);
520 tows = floor(tow * 1000.0 + 0.5) / 1000.0; /* round by 1ms */
521 time = gpst2time(week, tows);
522
523 /* time tag offset correction */
524 if (strstr(raw->opt, "-TTCORR")) {
525 toff = CLIGHT * (tows - tow);
526 }
527 if (fabs(timediff(time, raw->time)) < 1e-9) {
528 n = raw->obs.n;
529 }
530 for (i = 0, p += 16; i < 12 && n < MAXOBS; i++) {
531 word1 = U4(p + 288 + 4 * i); /* L1CACodeMSBsSlot */
532 if ((prn = word1 & 0xFF) == 0) {
533 continue; /* if 0, no data */
534 }
535 if (!(sat = satno(SYS_GLO, prn))) {
536 trace(NULL, 2, "creasent bin 66 satellite number error: prn=%d\n", prn);
537 continue;
538 }
539 pr1 = (word1 >> 13) * 256.0; /* upper 19bit of L1CA pseudorange */
540
541 freq[0] = sat2freq(sat, CODE_L1C, &raw->nav);
542 freq[1] = sat2freq(sat, CODE_L2C, &raw->nav);
543
544 /* L1Obs */
545 word1 = U4(p + 12 * i);
546 word2 = U4(p + 4 + 12 * i);
547 word3 = U4(p + 8 + 12 * i);
548 sn = word1 & 0xFFF;
549 snr[0] = sn == 0 ? 0.0 : 10.0 * log10(0.1024 * sn) + SNR2CN0_L1;
550 sc = (uint32_t)(word1 >> 24);
551 if (raw->time.time != 0) {
552 lli[0] = (int)((uint8_t)sc - (uint8_t)raw->lockt[sat - 1][0]) > 0;
553 } else {
554 lli[0] = 0;
555 }
556 lli[0] |= ((word1 >> 12) & 7) ? 2 : 0;
557 raw->lockt[sat - 1][0] = (uint8_t)sc;
558 dop[0] = ((word2 >> 1) & 0x7FFFFF) / 512.0;
559 if ((word2 >> 24) & 1) {
560 dop[0] = -dop[0];
561 }
562 pr[0] = pr1 + (word3 & 0xFFFF) / 256.0;
563 cp[0] = floor(pr[0] * freq[0] / CLIGHT / 8192.0) * 8192.0;
564 cp[0] += ((word2 & 0xFE000000) + ((word3 & 0xFFFF0000) >> 7)) / 524288.0;
565 if (cp[0] - pr[0] * freq[0] / CLIGHT < -4096.0) {
566 cp[0] += 8192.0;
567 } else if (cp[0] - pr[0] * freq[0] / CLIGHT > 4096.0) {
568 cp[0] -= 8192.0;
569 }
570
571 /* L2Obs */
572 word1 = U4(p + 144 + 12 * i);
573 word2 = U4(p + 148 + 12 * i);
574 word3 = U4(p + 152 + 12 * i);
575 sn = word1 & 0xFFF;
576 snr[1] = sn == 0 ? 0.0 : 10.0 * log10(0.1164 * sn) + SNR2CN0_L2;
577 sc = (uint32_t)(word1 >> 24);
578 if (raw->time.time == 0) {
579 lli[1] = (int)((uint8_t)sc - (uint8_t)raw->lockt[sat - 1][1]) > 0;
580 } else {
581 lli[1] = 0;
582 }
583 lli[1] |= ((word1 >> 12) & 7) ? 2 : 0;
584 raw->lockt[sat - 1][1] = (uint8_t)sc;
585 dop[1] = ((word2 >> 1) & 0x7FFFFF) / 512.0;
586 if ((word2 >> 24) & 1) {
587 dop[1] = -dop[1];
588 }
589 pr[1] = (word3 & 0xFFFF) / 256.0;
590 if (pr[1] != 0.0) {
591 pr[1] += pr1;
592 if (pr[1] - pr[0] < -128.0) {
593 pr[1] += 256.0;
594 } else if (pr[1] - pr[0] > 128.0) {
595 pr[1] -= 256.0;
596 }
597 cp[1] = floor(pr[1] * freq[1] / CLIGHT / 8192.0) * 8192.0;
598 cp[1] += ((word2 & 0xFE000000) + ((word3 & 0xFFFF0000) >> 7)) / 524288.0;
599 if (cp[1] - pr[1] * freq[1] / CLIGHT < -4096.0) {
600 cp[1] += 8192.0;
601 } else if (cp[1] - pr[1] * freq[1] / CLIGHT > 4096.0) {
602 cp[1] -= 8192.0;
603 }
604 }
605 raw->obs.data[n].time = time;
606 raw->obs.data[n].sat = sat;
607 for (j = 0; j < NFREQ; j++) {
608 if (j == 0 || (j == 1 && i < 12)) {
609 raw->obs.data[n].P[j] = pr[j] == 0.0 ? 0.0 : pr[j] - toff;
610 raw->obs.data[n].L[j] = cp[j] == 0.0 ? 0.0 : cp[j] - toff * freq[j] / CLIGHT;
611 raw->obs.data[n].D[j] = -(float)dop[j];
612 raw->obs.data[n].SNR[j] = (uint16_t)(snr[j] / SNR_UNIT + 0.5);
613 raw->obs.data[n].LLI[j] = (uint8_t)lli[j];
614 raw->obs.data[n].code[j] = j == 0 ? CODE_L1C : CODE_L2P;
615 } else {
616 raw->obs.data[n].L[j] = raw->obs.data[n].P[j] = 0.0;
617 raw->obs.data[n].D[j] = 0.0;
618 raw->obs.data[n].SNR[j] = raw->obs.data[n].LLI[j] = 0;
619 raw->obs.data[n].code[j] = CODE_NONE;
620 }
621 }
622 n++;
623 }
624 raw->time = time;
625 raw->obs.n = n;
626 return 1;
627}
628/* decode bin 65 glonass ephemeris -------------------------------------------*/
629static int decode_cresgloeph(raw_t* raw) {
630 geph_t geph = {0};
631 uint8_t *p = raw->buff + 8, str[12];
632 int i, j, k, sat, prn, frq, time, no;
633
634 trace(NULL, 4, "decode_cregloeph: len=%d\n", raw->len);
635
636 if (!strstr(raw->opt, "-ENAGLO")) {
637 return 0;
638 }
639
640 prn = U1(p);
641 p += 1;
642 frq = U1(p) - 8;
643 p += 1 + 2;
644 time = U4(p);
645 p += 4;
646
647 if (!(sat = satno(SYS_GLO, prn))) {
648 trace(NULL, 2, "creasent bin 65 satellite number error: prn=%d\n", prn);
649 return -1;
650 }
651 for (i = 0; i < 5; i++) {
652 for (j = 0; j < 3; j++) {
653 for (k = 3; k >= 0; k--) {
654 str[k + j * 4] = U1(p++);
655 }
656 }
657 if ((no = getbitu(str, 1, 4)) != i + 1) {
658 trace(NULL, 2, "creasent bin 65 string no error: sat=%2d no=%d %d\n", sat, i + 1, no);
659 return -1;
660 }
661 memcpy(raw->subfrm[sat - 1] + 10 * i, str, 10);
662 }
663 /* decode glonass ephemeris strings */
664 geph.tof = raw->time;
665 if (!decode_glostr(raw->subfrm[sat - 1], &geph, NULL) || geph.sat != sat) {
666 return -1;
667 }
668 geph.frq = frq;
669
670 if (!strstr(raw->opt, "-EPHALL")) {
671 if (geph.iode == raw->nav.geph[prn - 1].iode) {
672 return 0; /* unchanged */
673 }
674 }
675 raw->nav.geph[prn - 1] = geph;
676 raw->ephsat = sat;
677 raw->ephset = 0;
678 return 2;
679}
680/* decode crescent raw message -----------------------------------------------*/
681static int decode_cres(raw_t* raw) {
682 int type = U2(raw->buff + 4);
683
684 trace(NULL, 3, "decode_cres: type=%2d len=%d\n", type, raw->len);
685
686 if (!chksum(raw->buff, raw->len)) {
687 trace(NULL, 2, "crescent checksum error: type=%2d len=%d\n", type, raw->len);
688 return -1;
689 }
690 if (raw->outtype) {
691 sprintf(raw->msgtype, "HEMIS %2d (%4d):", type, raw->len);
692 }
693 switch (type) {
694 case ID_CRESPOS:
695 return decode_crespos(raw);
696 case ID_CRESRAW:
697 return decode_cresraw(raw);
698 case ID_CRESRAW2:
699 return decode_cresraw2(raw);
700 case ID_CRESEPH:
701 return decode_creseph(raw);
702 case ID_CRESWAAS:
703 return decode_creswaas(raw);
704 case ID_CRESIONUTC:
705 return decode_cresionutc(raw);
706 case ID_CRESGLORAW:
707 return decode_cresgloraw(raw);
708 case ID_CRESGLOEPH:
709 return decode_cresgloeph(raw);
710 }
711 return 0;
712}
713/* sync code -----------------------------------------------------------------*/
714static int sync_cres(uint8_t* buff, uint8_t data) {
715 buff[0] = buff[1];
716 buff[1] = buff[2];
717 buff[2] = buff[3];
718 buff[3] = data;
719 return buff[0] == CRESSYNC[0] && buff[1] == CRESSYNC[1] && buff[2] == CRESSYNC[2] && buff[3] == CRESSYNC[3];
720}
721/* input cresent raw message ---------------------------------------------------
722 * input next crescent raw message from stream
723 * args : raw_t *raw IO receiver raw data control struct
724 * uint8_t data I stream data (1 byte)
725 * return : status (-1: error message, 0: no message, 1: input observation data,
726 * 2: input ephemeris, 3: input sbas message,
727 * 9: input ion/utc parameter)
728 *
729 * notes : to specify input options, set raw->opt to the following option
730 * strings separated by spaces.
731 *
732 * -EPHALL : input all ephemerides
733 * -TTCORR : time-tag offset correction
734 * -ENAGLO : enable glonass messages
735 *
736 *-----------------------------------------------------------------------------*/
737extern int input_cres(raw_t* raw, uint8_t data) {
738 trace(NULL, 5, "input_cres: data=%02x\n", data);
739
740 /* synchronize frame */
741 if (raw->nbyte == 0) {
742 if (!sync_cres(raw->buff, data)) {
743 return 0;
744 }
745 raw->nbyte = 4;
746 return 0;
747 }
748 raw->buff[raw->nbyte++] = data;
749
750 if (raw->nbyte == 8) {
751 if ((raw->len = U2(raw->buff + 6) + 12) > MAXRAWLEN) {
752 trace(NULL, 2, "cresent length error: len=%d\n", raw->len);
753 raw->nbyte = 0;
754 return -1;
755 }
756 }
757 if (raw->nbyte < 8 || raw->nbyte < raw->len) {
758 return 0;
759 }
760 raw->nbyte = 0;
761
762 /* decode crescent raw message */
763 return decode_cres(raw);
764}
765/* input crescent raw message from file ----------------------------------------
766 * input next crescent raw message from file
767 * args : raw_t *raw IO receiver raw data control struct
768 * FILE *fp I file pointer
769 * return : status(-2: end of file, -1...9: same as above)
770 *-----------------------------------------------------------------------------*/
771extern int input_cresf(raw_t* raw, FILE* fp) {
772 int i, data;
773
774 trace(NULL, 4, "input_cresf:\n");
775
776 /* synchronize frame */
777 if (raw->nbyte == 0) {
778 for (i = 0;; i++) {
779 if ((data = fgetc(fp)) == EOF) {
780 return -2;
781 }
782 if (sync_cres(raw->buff, (uint8_t)data)) {
783 break;
784 }
785 if (i >= 4096) {
786 return 0;
787 }
788 }
789 }
790 if (fread(raw->buff + 4, 1, 4, fp) < 4) {
791 return -2;
792 }
793 raw->nbyte = 8;
794
795 if ((raw->len = U2(raw->buff + 6) + 12) > MAXRAWLEN) {
796 trace(NULL, 2, "crescent length error: len=%d\n", raw->len);
797 raw->nbyte = 0;
798 return -1;
799 }
800 if (fread(raw->buff + 8, 1, raw->len - 8, fp) < (size_t)(raw->len - 8)) {
801 return -2;
802 }
803 raw->nbyte = 0;
804
805 /* decode crescent raw message */
806 return decode_cres(raw);
807}
uint32_t getbitu(const uint8_t *buff, int pos, int len)
Extract unsigned bits from byte data.
Definition mrtk_bits.c:99
MRTKLIB Bits Module — Binary bit operations and CRC functions.
double sat2freq(int sat, uint8_t code, const nav_t *nav)
Definition mrtk_obs.c:244
#define CLIGHT
Definition mrtk_coords.c:41
#define SYS_GPS
Definition mrtk_eph.c:65
#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_L2P
#define CODE_L1C
#define CODE_L2C
#define CODE_NONE
#define MAXRAWLEN
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 FREQ2
Definition mrtk_obs.c:68
#define FREQ1
Definition mrtk_obs.c:67
MRTKLIB Observation Module — Observation data types and utility functions.
#define MAXPRNSBS
#define MINPRNSBS
#define MAXPRNGPS
static int decode_cres(raw_t *raw)
#define U1(p)
#define ID_CRESGLOEPH
static int decode_creswaas(raw_t *raw)
#define CRESSYNC
#define ID_CRESGLORAW
#define ID_CRESEPH
#define ID_CRESWAAS
static int sync_cres(uint8_t *buff, uint8_t data)
#define ID_CRESIONUTC
#define ID_CRESRAW2
static int decode_crespos(raw_t *raw)
#define ID_CRESPOS
static int decode_cresraw(raw_t *raw)
static int decode_cresgloraw(raw_t *raw)
#define SNR2CN0_L2
static int chksum(const uint8_t *buff, int len)
static int decode_cresraw2(raw_t *raw)
#define ID_CRESRAW
#define SNR2CN0_L1
static int decode_cresgloeph(raw_t *raw)
static int decode_creseph(raw_t *raw)
int input_cres(raw_t *raw, uint8_t data)
static int decode_cresionutc(raw_t *raw)
int input_cresf(raw_t *raw, FILE *fp)
#define R8(p)
#define U4(p)
#define I4(p)
#define R4(p)
#define U2(p)
#define I2(p)
int decode_frame(const uint8_t *buff, eph_t *eph, alm_t *alm, double *ion, double *utc)
int decode_glostr(const uint8_t *buff, geph_t *geph, double *utc)
MRTKLIB Receiver Raw Data Module — Receiver raw data types and decoder functions for various GNSS rec...
MRTKLIB RTCM Module — RTCM message types and functions.
MRTKLIB System Module — OS/filesystem utility functions.
gtime_t gpst2time(int week, double sec)
Convert GPS week/tow to gtime_t.
Definition mrtk_time.c:165
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
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
int sat
Definition mrtk_eph.h:78
int iode
Definition mrtk_eph.h:79
GLONASS broadcast ephemeris type.
Definition mrtk_eph.h:111
int iode
Definition mrtk_eph.h:113
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
uint8_t subfrm[MAXSAT][380]
Definition mrtk_rcvraw.h:89
nav_t nav
Definition mrtk_rcvraw.h:83
double lockt[MAXSAT][5+5]
Definition mrtk_rcvraw.h:90
int ephset
Definition mrtk_rcvraw.h:86
int outtype
obs_t obs
Definition mrtk_rcvraw.h:81
int len
Definition mrtk_rcvraw.h:96
uint8_t buff[MAXRAWLEN]
char msgtype[256]
Definition mrtk_rcvraw.h:88
int nbyte
Definition mrtk_rcvraw.h:95
char opt[256]
int ephsat
Definition mrtk_rcvraw.h:85
gtime_t time
Definition mrtk_rcvraw.h:79
int tow
Definition mrtk_nav.h:102
uint8_t msg[29]
Definition mrtk_nav.h:104
uint8_t prn
Definition mrtk_nav.h:103
int week
Definition mrtk_nav.h:102