source: ntrip/trunk/BNC/src/RTCM3/RTCM3Decoder.cpp@ 11084

Last change on this file since 11084 was 11084, checked in by stuerze, 10 days ago

bug fixd in RTCM3 decoder

File size: 78.8 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: RTCM3Decoder
30 *
31 * Purpose: RTCM3 Decoder
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Aug-2006
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include <iomanip>
43#include <sstream>
44#include <math.h>
45#include <string.h>
46
47#include "bits.h"
48#include "gnss.h"
49#include "RTCM3Decoder.h"
50#include "rtcm_utils.h"
51#include "bncconst.h"
52#include "bnccore.h"
53#include "bncutils.h"
54#include "bncsettings.h"
55#include "bnctime.h"
56#include "crs.h"
57
58using namespace std;
59
60// Error Handling
61////////////////////////////////////////////////////////////////////////////
62void RTCM3Error(const char*, ...) {
63}
64
65// Constructor
66////////////////////////////////////////////////////////////////////////////
67RTCM3Decoder::RTCM3Decoder(const QString& staID, bncRawFile* rawFile) :
68 GPSDecoder() {
69
70 _staID = staID;
71 _rawFile = rawFile;
72
73 Qt::ConnectionType conType = BNC_CORE->decoderConnectionType();
74 connect(this, SIGNAL(newGPSEph(t_ephGPS)), BNC_CORE, SLOT(slotNewGPSEph(t_ephGPS)), conType);
75 connect(this, SIGNAL(newGlonassEph(t_ephGlo)), BNC_CORE, SLOT(slotNewGlonassEph(t_ephGlo)), conType);
76 connect(this, SIGNAL(newGalileoEph(t_ephGal)), BNC_CORE, SLOT(slotNewGalileoEph(t_ephGal)), conType);
77 connect(this, SIGNAL(newSBASEph(t_ephSBAS)), BNC_CORE, SLOT(slotNewSBASEph(t_ephSBAS)), conType);
78 connect(this, SIGNAL(newBDSEph(t_ephBDS)), BNC_CORE, SLOT(slotNewBDSEph(t_ephBDS)), conType);
79
80 _MessageSize = _SkipBytes = _BlockSize = _NeedBytes = 0;
81}
82
83// Destructor
84////////////////////////////////////////////////////////////////////////////
85RTCM3Decoder::~RTCM3Decoder() {
86 QMapIterator<QByteArray, RTCM3coDecoder*> it(_coDecoders);
87 while (it.hasNext()) {
88 it.next();
89 delete it.value();
90 }
91 _coDecoders.clear();
92}
93
94// Pass on the corrections still held back by the SSR decoders
95////////////////////////////////////////////////////////////////////////////
96void RTCM3Decoder::flush() {
97 QMapIterator<QByteArray, RTCM3coDecoder*> it(_coDecoders);
98 while (it.hasNext()) {
99 it.next();
100 it.value()->flush();
101 }
102}
103
104//
105////////////////////////////////////////////////////////////////////////////
106bool RTCM3Decoder::DecodeRTCM3GPS(unsigned char* data, int size) {
107 bool decoded = false;
108 bncTime CurrentObsTime;
109 int i, numsats, syncf, type;
110 uint64_t numbits = 0, bitfield = 0;
111
112 data += 3; /* header */
113 size -= 6; /* header + crc */
114
115 GETBITS(type, 12)
116 SKIPBITS(12)
117 /* id */
118 GETBITS(i, 30)
119
120 CurrentObsTime.set(i);
121 if (_CurrentTime.valid() && CurrentObsTime != _CurrentTime) {
122 decoded = true;
123 _obsList.append(_CurrentObsList);
124 _CurrentObsList.clear();
125 }
126
127 _CurrentTime = CurrentObsTime;
128
129 GETBITS(syncf, 1)
130 /* sync */
131 GETBITS(numsats, 5)
132 SKIPBITS(4)
133 /* smind, smint */
134
135 while (numsats--) {
136 int sv, code, l1range, amb = 0;
137 t_satObs CurrentObs;
138 CurrentObs._time = CurrentObsTime;
139 CurrentObs._type = type;
140
141 GETBITS(sv, 6)
142 char sys;
143 int num, flag;
144 if (sv < 40) {
145 sys = 'G';
146 num = sv;
147 }
148 else {
149 sys = 'S';
150 num = sv - 20;
151 }
152 flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
153 CurrentObs._prn.set(sys, num, flag);
154 checkPrnRange(CurrentObs._prn);
155
156 t_frqObs *frqObs = new t_frqObs;
157 /* L1 */
158 GETBITS(code, 1);
159 (code) ?
160 frqObs->_rnxType2ch.assign("1W") : frqObs->_rnxType2ch.assign("1C");
161 GETBITS(l1range, 24);
162 GETBITSSIGN(i, 20);
163 if ((i & ((1 << 20) - 1)) != 0x80000) {
164 frqObs->_code = l1range * 0.02;
165 frqObs->_phase = (l1range * 0.02 + i * 0.0005) / GPS_WAVELENGTH_L1;
166 frqObs->_codeValid = frqObs->_phaseValid = true;
167 }
168 GETBITS(frqObs->_lockTimeIndicator, 7);
169 frqObs->_lockTime = lti2sec(type, frqObs->_lockTimeIndicator);
170 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0 && frqObs->_phaseValid);
171 if (type == 1002 || type == 1004) {
172 GETBITS(amb, 8);
173 if (amb) {
174 frqObs->_code += amb * 299792.458;
175 frqObs->_phase += (amb * 299792.458) / GPS_WAVELENGTH_L1;
176 }
177 GETBITS(i, 8);
178 if (i) {
179 frqObs->_snr = i * 0.25;
180 frqObs->_snrValid = true;
181 }
182 }
183 CurrentObs._obs.push_back(frqObs);
184 if (type == 1003 || type == 1004) {
185 frqObs = new t_frqObs;
186 /* L2 */
187 GETBITS(code, 2);
188 switch (code) {
189 case 3:
190 frqObs->_rnxType2ch.assign("2W"); /* or "2Y"? */
191 break;
192 case 2:
193 frqObs->_rnxType2ch.assign("2W");
194 break;
195 case 1:
196 frqObs->_rnxType2ch.assign("2P");
197 break;
198 case 0:
199 frqObs->_rnxType2ch.assign("2X"); /* or "2S" or "2L"? */
200 break;
201 }
202 GETBITSSIGN(i, 14);
203 if ((i & ((1 << 14) - 1)) != 0x2000) {
204 frqObs->_code = l1range * 0.02 + i * 0.02 + amb * 299792.458;
205 frqObs->_codeValid = true;
206 }
207 GETBITSSIGN(i, 20);
208 if ((i & ((1 << 20) - 1)) != 0x80000) {
209 frqObs->_phase = (l1range * 0.02 + i * 0.0005 + amb * 299792.458)
210 / GPS_WAVELENGTH_L2;
211 frqObs->_phaseValid = true;
212 }
213 GETBITS(frqObs->_lockTimeIndicator, 7);
214 frqObs->_lockTime = lti2sec(type, frqObs->_lockTimeIndicator);
215 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0 && frqObs->_phaseValid);
216 if (type == 1004) {
217 GETBITS(i, 8);
218 if (i) {
219 frqObs->_snr = i * 0.25;
220 frqObs->_snrValid = true;
221 }
222 }
223 CurrentObs._obs.push_back(frqObs);
224 }
225 _CurrentObsList.push_back(CurrentObs);
226 }
227
228 if (!syncf) {
229 decoded = true;
230 _obsList.append(_CurrentObsList);
231 _CurrentTime.reset();
232 _CurrentObsList.clear();
233 }
234 return decoded;
235}
236
237#define RTCM3_MSM_NUMSIG 32
238#define RTCM3_MSM_NUMSAT 64
239#define RTCM3_MSM_NUMCELLS 96 /* arbitrary limit */
240
241/**
242 * Frequency numbers of GLONASS with an offset of 100 to detect unset values.
243 * Gets filled by ephemeris and data blocks and shared between different streams.
244 */
245static int GLOFreq[RTCM3_MSM_NUMSAT];
246
247/*
248 * Storage structure to store frequency and RINEX ID assignment for MSM
249 * message */
250struct CodeData {
251 double wl;
252 const char *code; /* currently unused */
253};
254
255/** MSM signal types for GPS and SBAS */
256static struct CodeData gps[RTCM3_MSM_NUMSIG] = {
257 {0.0, 0},
258 {GPS_WAVELENGTH_L1, "1C"},
259 {GPS_WAVELENGTH_L1, "1P"},
260 {GPS_WAVELENGTH_L1, "1W"},
261 {0.0, 0},
262 {0.0, 0},
263 {0.0, 0},
264 {GPS_WAVELENGTH_L2, "2C"},
265 {GPS_WAVELENGTH_L2, "2P"},
266 {GPS_WAVELENGTH_L2, "2W"},
267 {0.0, 0},
268 {0.0, 0},
269 {0.0, 0},
270 {0.0, 0},
271 {GPS_WAVELENGTH_L2, "2S"},
272 {GPS_WAVELENGTH_L2, "2L"},
273 {GPS_WAVELENGTH_L2, "2X"},
274 {0.0, 0},
275 {0.0, 0},
276 {0.0, 0},
277 {0.0, 0},
278 {GPS_WAVELENGTH_L5, "5I"},
279 {GPS_WAVELENGTH_L5, "5Q"},
280 {GPS_WAVELENGTH_L5, "5X"},
281 {0.0, 0},
282 {0.0, 0},
283 {0.0, 0},
284 {0.0, 0},
285 {0.0, 0},
286 {GPS_WAVELENGTH_L1, "1S"},
287 {GPS_WAVELENGTH_L1, "1L"},
288 {GPS_WAVELENGTH_L1, "1X"}
289 };
290
291/**
292 * MSM signal types for GLONASS
293 *
294 * NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later!
295 */
296static struct CodeData glo[RTCM3_MSM_NUMSIG] = {
297 {0.0, 0},
298 {0.0, "1C"},
299 {0.0, "1P"},
300 {0.0, 0},
301 {0.0, 0},
302 {0.0, 0},
303 {0.0, 0},
304 {1.0, "2C"},
305 {1.0, "2P"},
306 {GLO_WAVELENGTH_L1a, "4A"},
307 {GLO_WAVELENGTH_L1a, "4B"},
308 {GLO_WAVELENGTH_L1a, "4X"},
309 {GLO_WAVELENGTH_L2a, "6A"},
310 {GLO_WAVELENGTH_L2a, "6B"},
311 {GLO_WAVELENGTH_L2a, "6X"},
312 {GLO_WAVELENGTH_L3, "3I"},
313 {GLO_WAVELENGTH_L3, "3Q"},
314 {GLO_WAVELENGTH_L3, "3X"},
315 {0.0, 0},
316 {0.0, 0},
317 {0.0, 0},
318 {0.0, 0},
319 {0.0, 0},
320 {0.0, 0},
321 {0.0, 0},
322 {0.0, 0},
323 {0.0, 0},
324 {0.0, 0},
325 {0.0, 0},
326 {0.0, 0},
327 {0.0, 0},
328 {0.0, 0}
329 };
330
331/** MSM signal types for Galileo */
332static struct CodeData gal[RTCM3_MSM_NUMSIG] = {
333 {0.0, 0},
334 {GAL_WAVELENGTH_E1, "1C"},
335 {GAL_WAVELENGTH_E1, "1A"},
336 {GAL_WAVELENGTH_E1, "1B"},
337 {GAL_WAVELENGTH_E1, "1X"},
338 {GAL_WAVELENGTH_E1, "1Z"},
339 {0.0, 0},
340 {GAL_WAVELENGTH_E6, "6C"},
341 {GAL_WAVELENGTH_E6, "6A"},
342 {GAL_WAVELENGTH_E6, "6B"},
343 {GAL_WAVELENGTH_E6, "6X"},
344 {GAL_WAVELENGTH_E6, "6Z"},
345 {0.0, 0},
346 {GAL_WAVELENGTH_E5B, "7I"},
347 {GAL_WAVELENGTH_E5B, "7Q"},
348 {GAL_WAVELENGTH_E5B, "7X"},
349 {0.0, 0},
350 {GAL_WAVELENGTH_E5AB,"8I"},
351 {GAL_WAVELENGTH_E5AB,"8Q"},
352 {GAL_WAVELENGTH_E5AB,"8X"},
353 {0.0, 0},
354 {GAL_WAVELENGTH_E5A, "5I"},
355 {GAL_WAVELENGTH_E5A, "5Q"},
356 {GAL_WAVELENGTH_E5A, "5X"},
357 {0.0, 0},
358 {0.0, 0},
359 {0.0, 0},
360 {0.0, 0},
361 {0.0, 0},
362 {0.0, 0},
363 {0.0, 0},
364 {0.0, 0}
365 };
366
367/** MSM signal types for QZSS */
368static struct CodeData qzss[RTCM3_MSM_NUMSIG] = {
369 {0.0, 0},
370 {GPS_WAVELENGTH_L1, "1C"},
371 {GPS_WAVELENGTH_L1, "1E"},
372 {0.0, 0},
373 {0.0, 0},
374 {0.0, 0},
375 {0.0, 0},
376 {0.0, 0},
377 {QZSS_WAVELENGTH_L6, "6S"},
378 {QZSS_WAVELENGTH_L6, "6L"},
379 {QZSS_WAVELENGTH_L6, "6X"},
380 {0.0, 0},
381 {0.0, 0},
382 {0.0, 0},
383 {GPS_WAVELENGTH_L2, "2S"},
384 {GPS_WAVELENGTH_L2, "2L"},
385 {GPS_WAVELENGTH_L2, "2X"},
386 {0.0, 0},
387 {0.0, 0},
388 {0.0, 0},
389 {0.0, 0},
390 {GPS_WAVELENGTH_L5, "5I"},
391 {GPS_WAVELENGTH_L5, "5Q"},
392 {GPS_WAVELENGTH_L5, "5X"},
393 {0.0, 0},
394 {0.0, 0},
395 {0.0, 0},
396 {0.0, 0},
397 {0.0, 0},
398 {GPS_WAVELENGTH_L1, "1S"},
399 {GPS_WAVELENGTH_L1, "1L"},
400 {GPS_WAVELENGTH_L1, "1X"}
401 };
402
403/** MSM signal types for Beidou/BDS */
404static struct CodeData bds[RTCM3_MSM_NUMSIG] = {
405 {0.0, 0},
406 {BDS_WAVELENGTH_B1, "2I"},
407 {BDS_WAVELENGTH_B1, "2Q"},
408 {BDS_WAVELENGTH_B1, "2X"},
409 {0.0, 0},
410 {0.0, 0},
411 {0.0, 0},
412 {BDS_WAVELENGTH_B3, "6I"},
413 {BDS_WAVELENGTH_B3, "6Q"},
414 {BDS_WAVELENGTH_B3, "6X"},
415 {0.0, 0},
416 {0.0, 0},
417 {0.0, 0},
418 {BDS_WAVELENGTH_B2, "7I"},
419 {BDS_WAVELENGTH_B2, "7Q"},
420 {BDS_WAVELENGTH_B2, "7X"},
421 {0.0, 0},
422 {0.0, 0},
423 {0.0, 0},
424 {0.0, 0},
425 {0.0, 0},
426 {BDS_WAVELENGTH_B2a, "5D"},
427 {BDS_WAVELENGTH_B2a, "5P"},
428 {BDS_WAVELENGTH_B2a, "5X"},
429 {BDS_WAVELENGTH_B2b, "7D"},
430 {0.0, 0},
431 {0.0, 0},
432 {0.0, 0},
433 {0.0, 0},
434 {BDS_WAVELENGTH_B1C, "1D"},
435 {BDS_WAVELENGTH_B1C, "1P"},
436 {BDS_WAVELENGTH_B1C, "1X"}
437 };
438
439/** MSM signal types for NavIC */
440static struct CodeData irn[RTCM3_MSM_NUMSIG] = {
441 {0.0, 0},
442 {0.0, 0},
443 {0.0, 0},
444 {0.0, 0},
445 {0.0, 0},
446 {0.0, 0},
447 {0.0, 0},
448 {NavIC_WAVELENGTH_S, "9A"},
449 {0.0, 0},
450 {0.0, 0},
451 {0.0, 0},
452 {0.0, 0},
453 {0.0, 0},
454 {0.0, 0},
455 {0.0, 0},
456 {0.0, 0},
457 {0.0, 0},
458 {0.0, 0},
459 {0.0, 0},
460 {0.0, 0},
461 {0.0, 0},
462 {NavIC_WAVELENGTH_L5, "5A"},
463 {0.0, 0},
464 {0.0, 0},
465 {0.0, 0},
466 {0.0, 0},
467 {0.0, 0},
468 {0.0, 0},
469 {0.0, 0},
470 {0.0, 0},
471 {0.0, 0},
472 {0.0, 0}
473 };
474
475#define UINT64(c) c ## ULL
476
477//
478////////////////////////////////////////////////////////////////////////////
479bool RTCM3Decoder::DecodeRTCM3MSM(unsigned char* data, int size) {
480 bool decoded = false;
481 int type, syncf, i;
482 uint64_t numbits = 0, bitfield = 0;
483
484 data += 3; /* header */
485 size -= 6; /* header + crc */
486
487 GETBITS(type, 12)
488 SKIPBITS(12)
489 /* id */
490 char sys;
491 if (type >= 1131 && type <= 1137) {
492 sys = 'I';
493 }
494 else if (type >= 1121 && type <= 1127) {
495 sys = 'C';
496 }
497 else if (type >= 1111 && type <= 1117) {
498 sys = 'J';
499 }
500 else if (type >= 1101 && type <= 1107) {
501 sys = 'S';
502 }
503 else if (type >= 1091 && type <= 1097) {
504 sys = 'E';
505 }
506 else if (type >= 1081 && type <= 1087) {
507 sys = 'R';
508 }
509 else if (type >= 1071 && type <= 1077) {
510 sys = 'G';
511 }
512 else {
513 return decoded; // false
514 }
515 bncTime CurrentObsTime;
516 if (sys == 'C') /* BDS */ {
517 GETBITS(i, 30)
518 CurrentObsTime.setBDS(i);
519 }
520 else if (sys == 'R') /* GLONASS */ {
521 SKIPBITS(3)
522 GETBITS(i, 27)
523 /* tk */
524 CurrentObsTime.setTk(i);
525 }
526 else /* GPS style date */ {
527 GETBITS(i, 30)
528 CurrentObsTime.set(i);
529 }
530 if (_CurrentTime.valid() && CurrentObsTime != _CurrentTime) {
531 decoded = true;
532 _obsList.append(_CurrentObsList);
533 _CurrentObsList.clear();
534 }
535 _CurrentTime = CurrentObsTime;
536
537 GETBITS(syncf, 1)
538 /**
539 * Ignore unknown types except for sync flag
540 *
541 * We actually support types 1-3 in following code, but as they are missing
542 * the full cycles and can't be used later we skip interpretation here already.
543 */
544 if (type <= 1137 && (type % 10) >= 4 && (type % 10) <= 7) {
545 int sigmask, numsat = 0, numsig = 0;
546 uint64_t satmask, cellmask, ui;
547 // satellite data
548 double rrmod[RTCM3_MSM_NUMSAT]; // GNSS sat rough ranges modulo 1 millisecond
549 int rrint[RTCM3_MSM_NUMSAT]; // number of integer msecs in GNSS sat rough ranges
550 int rdop[RTCM3_MSM_NUMSAT]; // GNSS sat rough phase range rates
551 int extsat[RTCM3_MSM_NUMSAT];// extended sat info
552 // signal data
553 int ll[RTCM3_MSM_NUMCELLS]; // lock time indicator
554 /*int hc[RTCM3_MSM_NUMCELLS];*/ // half cycle ambiguity indicator
555 double cnr[RTCM3_MSM_NUMCELLS]; // signal cnr
556 double cp[RTCM3_MSM_NUMCELLS]; // fine phase range data
557 double psr[RTCM3_MSM_NUMCELLS]; // fine psr
558 double dop[RTCM3_MSM_NUMCELLS]; // fine phase range rates
559
560 SKIPBITS(3 + 7 + 2 + 2 + 1 + 3)
561 GETBITS64(satmask, RTCM3_MSM_NUMSAT)
562
563 /* http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/ */
564 for (ui = satmask; ui; ui &= (ui - 1) /* remove rightmost bit */)
565 ++numsat;
566 GETBITS(sigmask, RTCM3_MSM_NUMSIG)
567 for (i = sigmask; i; i &= (i - 1) /* remove rightmost bit */)
568 ++numsig;
569 for (i = 0; i < RTCM3_MSM_NUMSAT; ++i)
570 extsat[i] = 15;
571
572 i = numsat * numsig;
573 GETBITS64(cellmask, (unsigned )i)
574 // satellite data
575 switch (type % 10) {
576 case 1:
577 case 2:
578 case 3:
579 /* partial data, already skipped above, but implemented for future expansion ! */
580 for (int j = numsat; j--;)
581 GETFLOAT(rrmod[j], 10, 1.0 / 1024.0)
582 break;
583 case 4:
584 case 6:
585 for (int j = numsat; j--;)
586 GETBITS(rrint[j], 8)
587 for (int j = numsat; j--;)
588 GETFLOAT(rrmod[j], 10, 1.0 / 1024.0)
589 break;
590 case 5:
591 case 7:
592 for (int j = numsat; j--;)
593 GETBITS(rrint[j], 8)
594 for (int j = numsat; j--;)
595 GETBITS(extsat[j], 4)
596 for (int j = numsat; j--;)
597 GETFLOAT(rrmod[j], 10, 1.0 / 1024.0)
598 for (int j = numsat; j--;)
599 GETBITSSIGN(rdop[j], 14)
600 break;
601 }
602 // signal data
603 int numcells = numsat * numsig;
604 /** Drop anything which exceeds our cell limit. Increase limit definition
605 * when that happens. */
606 if (numcells <= RTCM3_MSM_NUMCELLS) {
607 switch (type % 10) {
608 case 1:
609 for (int count = numcells; count--;)
610 if (cellmask & (UINT64(1) << count))
611 GETFLOATSIGN(psr[count], 15, 1.0 / (1 << 24))
612 break;
613 case 2:
614 for (int count = numcells; count--;)
615 if (cellmask & (UINT64(1) << count))
616 GETFLOATSIGN(cp[count], 22, 1.0 / (1 << 29))
617 for (int count = numcells; count--;)
618 if (cellmask & (UINT64(1) << count))
619 GETBITS(ll[count], 4)
620 for (int count = numcells; count--;)
621 if (cellmask & (UINT64(1) << count))
622 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
623 break;
624 case 3:
625 for (int count = numcells; count--;)
626 if (cellmask & (UINT64(1) << count))
627 GETFLOATSIGN(psr[count], 15, 1.0 / (1 << 24))
628 for (int count = numcells; count--;)
629 if (cellmask & (UINT64(1) << count))
630 GETFLOATSIGN(cp[count], 22, 1.0 / (1 << 29))
631 for (int count = numcells; count--;)
632 if (cellmask & (UINT64(1) << count))
633 GETBITS(ll[count], 4)
634 for (int count = numcells; count--;)
635 if (cellmask & (UINT64(1) << count))
636 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
637 break;
638 case 4:
639 for (int count = numcells; count--;)
640 if (cellmask & (UINT64(1) << count))
641 GETFLOATSIGN(psr[count], 15, 1.0 / (1 << 24))
642 for (int count = numcells; count--;)
643 if (cellmask & (UINT64(1) << count))
644 GETFLOATSIGN(cp[count], 22, 1.0 / (1 << 29))
645 for (int count = numcells; count--;)
646 if (cellmask & (UINT64(1) << count))
647 GETBITS(ll[count], 4)
648 for (int count = numcells; count--;)
649 if (cellmask & (UINT64(1) << count))
650 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
651 for (int count = numcells; count--;)
652 if (cellmask & (UINT64(1) << count))
653 GETBITS(cnr[count], 6)
654 break;
655 case 5:
656 for (int count = numcells; count--;)
657 if (cellmask & (UINT64(1) << count))
658 GETFLOATSIGN(psr[count], 15, 1.0 / (1 << 24))
659 for (int count = numcells; count--;)
660 if (cellmask & (UINT64(1) << count))
661 GETFLOATSIGN(cp[count], 22, 1.0 / (1 << 29))
662 for (int count = numcells; count--;)
663 if (cellmask & (UINT64(1) << count))
664 GETBITS(ll[count], 4)
665 for (int count = numcells; count--;)
666 if (cellmask & (UINT64(1) << count))
667 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
668 for (int count = numcells; count--;)
669 if (cellmask & (UINT64(1) << count))
670 GETFLOAT(cnr[count], 6, 1.0)
671 for (int count = numcells; count--;)
672 if (cellmask & (UINT64(1) << count))
673 GETFLOATSIGN(dop[count], 15, 0.0001)
674 break;
675 case 6:
676 for (int count = numcells; count--;)
677 if (cellmask & (UINT64(1) << count))
678 GETFLOATSIGN(psr[count], 20, 1.0 / (1 << 29))
679 for (int count = numcells; count--;)
680 if (cellmask & (UINT64(1) << count))
681 GETFLOATSIGN(cp[count], 24, 1.0 / (1U << 31))
682 for (int count = numcells; count--;)
683 if (cellmask & (UINT64(1) << count))
684 GETBITS(ll[count], 10)
685 for (int count = numcells; count--;)
686 if (cellmask & (UINT64(1) << count))
687 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
688 for (int count = numcells; count--;)
689 if (cellmask & (UINT64(1) << count))
690 GETFLOAT(cnr[count], 10, 1.0 / (1 << 4))
691 break;
692 case 7:
693 for (int count = numcells; count--;)
694 if (cellmask & (UINT64(1) << count))
695 GETFLOATSIGN(psr[count], 20, 1.0 / (1 << 29))
696 for (int count = numcells; count--;)
697 if (cellmask & (UINT64(1) << count))
698 GETFLOATSIGN(cp[count], 24, 1.0 / (1U << 31))
699 for (int count = numcells; count--;)
700 if (cellmask & (UINT64(1) << count))
701 GETBITS(ll[count], 10)
702 for (int count = numcells; count--;)
703 if (cellmask & (UINT64(1) << count))
704 SKIPBITS(1)/*GETBITS(hc[count], 1)*/
705 for (int count = numcells; count--;)
706 if (cellmask & (UINT64(1) << count))
707 GETFLOAT(cnr[count], 10, 1.0 / (1 << 4))
708 for (int count = numcells; count--;)
709 if (cellmask & (UINT64(1) << count))
710 GETFLOATSIGN(dop[count], 15, 0.0001)
711 break;
712 }
713 i = RTCM3_MSM_NUMSAT;
714 int j = -1;
715 t_satObs CurrentObs;
716 for (int count = numcells; count--;) {
717 while (j >= 0 && !(sigmask & (1 << --j)))
718 ;
719 if (j < 0) {
720 while (!(satmask & (UINT64(1) << (--i))))
721 /* next satellite */
722 ;
723 if (CurrentObs._obs.size() > 0) {
724 char sys = CurrentObs._prn.system();
725 int num = CurrentObs._prn.number();
726 int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
727 CurrentObs._prn.setFlag(flag);
728 _CurrentObsList.push_back(CurrentObs);
729 }
730 CurrentObs.clear();
731 CurrentObs._time = CurrentObsTime;
732 CurrentObs._type = type;
733 if (sys == 'S')
734 CurrentObs._prn.set(sys, 20 - 1 + RTCM3_MSM_NUMSAT - i);
735 else
736 CurrentObs._prn.set(sys, RTCM3_MSM_NUMSAT - i);
737 checkPrnRange(CurrentObs._prn);
738 j = RTCM3_MSM_NUMSIG;
739 while (!(sigmask & (1 << --j)))
740 ;
741 --numsat;
742 }
743 if (cellmask & (UINT64(1) << count)) {
744 struct CodeData cd = {0.0, 0};
745 switch (sys) {
746 case 'J':
747 cd = qzss[RTCM3_MSM_NUMSIG - j - 1];
748 break;
749 case 'C':
750 cd = bds[RTCM3_MSM_NUMSIG - j - 1];
751 break;
752 case 'G':
753 case 'S':
754 cd = gps[RTCM3_MSM_NUMSIG - j - 1];
755 break;
756 case 'R':
757 cd = glo[RTCM3_MSM_NUMSIG - j - 1];
758 {
759 int k = GLOFreq[RTCM3_MSM_NUMSAT - i - 1];
760 if (extsat[numsat] < 14) { // channel number is available as extended info for MSM5/7
761 k = GLOFreq[RTCM3_MSM_NUMSAT - i - 1] = 100 + extsat[numsat] - 7;
762 }
763 if (k) {
764 if (cd.wl == 0.0) {
765 cd.wl = GLO_WAVELENGTH_L1(k - 100);
766 }
767 else if (cd.wl == 1.0) {
768 cd.wl = GLO_WAVELENGTH_L2(k - 100);
769 }
770 }
771 else if (!k && cd.wl <= 1) {
772 cd.code = 0;
773 }
774 }
775 break;
776 case 'E':
777 cd = gal[RTCM3_MSM_NUMSIG - j - 1];
778 break;
779 case 'I':
780 cd = irn[RTCM3_MSM_NUMSIG - j - 1];
781 break;
782 }
783 if (cd.code) {
784 t_frqObs *frqObs = new t_frqObs;
785 frqObs->_rnxType2ch.assign(cd.code);
786
787 switch (type % 10) {
788 case 1:
789 if (psr[count] > -1.0 / (1 << 10)) {
790 frqObs->_code = psr[count] * LIGHTSPEED / 1000.0
791 + (rrmod[numsat]) * LIGHTSPEED / 1000.0;
792 frqObs->_codeValid = true;
793 }
794 break;
795 case 2:
796 if (cp[count] > -1.0 / (1 << 8)) {
797 frqObs->_phase = cp[count] * LIGHTSPEED / 1000.0 / cd.wl
798 + (rrmod[numsat]) * LIGHTSPEED / 1000.0 / cd.wl;
799 frqObs->_phaseValid = true;
800 frqObs->_lockTime = lti2sec(type,ll[count]);
801 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0);
802 frqObs->_lockTimeIndicator = ll[count];
803 }
804 break;
805 case 3:
806 if (psr[count] > -1.0 / (1 << 10)) {
807 frqObs->_code = psr[count] * LIGHTSPEED / 1000.0
808 + (rrmod[numsat]) * LIGHTSPEED / 1000.0;
809 frqObs->_codeValid = true;
810 }
811 if (cp[count] > -1.0 / (1 << 8)) {
812 frqObs->_phase = cp[count] * LIGHTSPEED / 1000.0 / cd.wl
813 + rrmod[numsat] * LIGHTSPEED / 1000.0 / cd.wl;
814 frqObs->_phaseValid = true;
815 frqObs->_lockTime = lti2sec(type,ll[count]);
816 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0);
817 frqObs->_lockTimeIndicator = ll[count];
818 }
819 break;
820 case 4:
821 if (psr[count] > -1.0 / (1 << 10)) {
822 frqObs->_code = psr[count] * LIGHTSPEED / 1000.0
823 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0;
824 frqObs->_codeValid = true;
825 }
826 if (cp[count] > -1.0 / (1 << 8)) {
827 frqObs->_phase = cp[count] * LIGHTSPEED / 1000.0 / cd.wl
828 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0 / cd.wl;
829 frqObs->_phaseValid = true;
830 frqObs->_lockTime = lti2sec(type,ll[count]);
831 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0);
832 frqObs->_lockTimeIndicator = ll[count];
833 }
834 frqObs->_snr = cnr[count];
835 frqObs->_snrValid = true;
836 break;
837 case 5:
838 if (psr[count] > -1.0 / (1 << 10)) {
839 frqObs->_code = psr[count] * LIGHTSPEED / 1000.0
840 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0;
841 frqObs->_codeValid = true;
842 }
843 if (cp[count] > -1.0 / (1 << 8)) {
844 frqObs->_phase = cp[count] * LIGHTSPEED / 1000.0 / cd.wl
845 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0 / cd.wl;
846 frqObs->_phaseValid = true;
847 frqObs->_lockTime = lti2sec(type,ll[count]);
848 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0);
849 frqObs->_lockTimeIndicator = ll[count];
850 }
851 frqObs->_snr = cnr[count];
852 frqObs->_snrValid = true;
853 if (dop[count] > -1.6384) {
854 frqObs->_doppler = -(dop[count] + rdop[numsat]) / cd.wl;
855 frqObs->_dopplerValid = true;
856 }
857 break;
858 case 6:
859 if (psr[count] > -1.0 / (1 << 10)) {
860 frqObs->_code = psr[count] * LIGHTSPEED / 1000.0
861 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0;
862 frqObs->_codeValid = true;
863 }
864 if (cp[count] > -1.0 / (1 << 8)) {
865 frqObs->_phase = cp[count] * LIGHTSPEED / 1000.0 / cd.wl
866 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0 / cd.wl;
867 frqObs->_phaseValid = true;
868 frqObs->_lockTime = lti2sec(type,ll[count]);
869 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0);
870 frqObs->_lockTimeIndicator = ll[count];
871 }
872
873 frqObs->_snr = cnr[count];
874 frqObs->_snrValid = true;
875 break;
876 case 7:
877 if (psr[count] > -1.0 / (1 << 10)) {
878 frqObs->_code = psr[count] * LIGHTSPEED / 1000.0
879 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0;
880 frqObs->_codeValid = true;
881 }
882 if (cp[count] > -1.0 / (1 << 8)) {
883 frqObs->_phase = cp[count] * LIGHTSPEED / 1000.0 / cd.wl
884 + (rrmod[numsat] + rrint[numsat]) * LIGHTSPEED / 1000.0 / cd.wl;
885 frqObs->_phaseValid = true;
886 frqObs->_lockTime = lti2sec(type,ll[count]);
887 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0);
888 frqObs->_lockTimeIndicator = ll[count];
889 }
890
891 frqObs->_snr = cnr[count];
892 frqObs->_snrValid = true;
893
894 if (dop[count] > -1.6384) {
895 frqObs->_doppler = -(dop[count] + rdop[numsat]) / cd.wl;
896 frqObs->_dopplerValid = true;
897 }
898 break;
899 }
900 CurrentObs._obs.push_back(frqObs);
901 }
902 }
903 }
904 if (CurrentObs._obs.size() > 0) {
905 char sys = CurrentObs._prn.system();
906 int num = CurrentObs._prn.number();
907 int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
908 CurrentObs._prn.setFlag(flag);
909 _CurrentObsList.push_back(CurrentObs);
910 }
911 }
912 }
913 else if ((type % 10) < 4) {
914#ifdef BNC_DEBUG_OBS
915 emit(newMessage(QString("%1: Block %2 contain partial data! Ignored!")
916 .arg(_staID).arg(type).toLatin1(), true));
917#endif
918 }
919 if (!syncf) {
920 decoded = true;
921 _obsList.append(_CurrentObsList);
922 _CurrentTime.reset();
923 _CurrentObsList.clear();
924 }
925 return decoded;
926}
927
928//
929////////////////////////////////////////////////////////////////////////////
930bool RTCM3Decoder::DecodeRTCM3GLONASS(unsigned char* data, int size) {
931 bool decoded = false;
932 bncTime CurrentObsTime;
933 int i, numsats, syncf, type;
934 uint64_t numbits = 0, bitfield = 0;
935
936 data += 3; /* header */
937 size -= 6; /* header + crc */
938
939 GETBITS(type, 12)
940 SKIPBITS(12)
941 /* id */
942 GETBITS(i, 27)
943 /* tk */
944
945 CurrentObsTime.setTk(i);
946 if (_CurrentTime.valid() && CurrentObsTime != _CurrentTime) {
947 decoded = true;
948 _obsList.append(_CurrentObsList);
949 _CurrentObsList.clear();
950 }
951 _CurrentTime = CurrentObsTime;
952
953 GETBITS(syncf, 1)
954 /* sync */
955 GETBITS(numsats, 5)
956 SKIPBITS(4)
957 /* smind, smint */
958
959 while (numsats--) {
960 int sv, code, l1range, amb = 0, freq;
961 t_satObs CurrentObs;
962 CurrentObs._time = CurrentObsTime;
963 CurrentObs._type = type;
964
965 GETBITS(sv, 6)
966 char sys = 'R';
967 int flag = t_corrSSR::getSsrNavTypeFlag(sys, sv);
968 CurrentObs._prn.set(sys, sv, flag);
969 checkPrnRange(CurrentObs._prn);
970 GETBITS(code, 1)
971 GETBITS(freq, 5)
972 if (sv >= 1) { /* 6-bit slot 1..63 fits GLOFreq[64]; 0 is invalid */
973 GLOFreq[sv - 1] = 100 + freq - 7; /* store frequency for other users (MSM) */
974 }
975
976 t_frqObs *frqObs = new t_frqObs;
977 /* L1 */
978 (code) ?
979 frqObs->_rnxType2ch.assign("1P") : frqObs->_rnxType2ch.assign("1C");
980 GETBITS(l1range, 25);
981 GETBITSSIGN(i, 20);
982 if ((i & ((1 << 20) - 1)) != 0x80000) {
983 frqObs->_code = l1range * 0.02;
984 frqObs->_phase = (l1range * 0.02 + i * 0.0005) / GLO_WAVELENGTH_L1(freq - 7);
985 frqObs->_codeValid = frqObs->_phaseValid = true;
986 }
987 GETBITS(frqObs->_lockTimeIndicator, 7);
988 frqObs->_lockTime = lti2sec(type, frqObs->_lockTimeIndicator);
989 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0 && frqObs->_phaseValid);
990 if (type == 1010 || type == 1012) {
991 GETBITS(amb, 7);
992 if (amb) {
993 frqObs->_code += amb * 599584.916;
994 frqObs->_phase += (amb * 599584.916) / GLO_WAVELENGTH_L1(freq - 7);
995 }
996 GETBITS(i, 8);
997 if (i) {
998 frqObs->_snr = i * 0.25;
999 frqObs->_snrValid = true;
1000 }
1001 }
1002 CurrentObs._obs.push_back(frqObs);
1003 if (type == 1011 || type == 1012) {
1004 frqObs = new t_frqObs;
1005 /* L2 */
1006 GETBITS(code, 2);
1007 switch (code) {
1008 case 3:
1009 frqObs->_rnxType2ch.assign("2P");
1010 break;
1011 case 2:
1012 frqObs->_rnxType2ch.assign("2P");
1013 break;
1014 case 1:
1015 frqObs->_rnxType2ch.assign("2P");
1016 break;
1017 case 0:
1018 frqObs->_rnxType2ch.assign("2C");
1019 break;
1020 }
1021 GETBITSSIGN(i, 14);
1022 if ((i & ((1 << 14) - 1)) != 0x2000) {
1023 frqObs->_code = l1range * 0.02 + i * 0.02 + amb * 599584.916;
1024 frqObs->_codeValid = true;
1025 }
1026 GETBITSSIGN(i, 20);
1027 if ((i & ((1 << 20) - 1)) != 0x80000) {
1028 frqObs->_phase = (l1range * 0.02 + i * 0.0005 + amb * 599584.916)
1029 / GLO_WAVELENGTH_L2(freq - 7);
1030 frqObs->_phaseValid = true;
1031 }
1032 GETBITS(frqObs->_lockTimeIndicator, 7);
1033 frqObs->_lockTime = lti2sec(type, frqObs->_lockTimeIndicator);
1034 frqObs->_lockTimeValid = (frqObs->_lockTime >= 0.0 && frqObs->_phaseValid);
1035 if (type == 1012) {
1036 GETBITS(i, 8);
1037 if (i) {
1038 frqObs->_snr = i * 0.25;
1039 frqObs->_snrValid = true;
1040 }
1041 }
1042 CurrentObs._obs.push_back(frqObs);
1043 }
1044 _CurrentObsList.push_back(CurrentObs);
1045 }
1046 if (!syncf) {
1047 decoded = true;
1048 _obsList.append(_CurrentObsList);
1049 _CurrentTime.reset();
1050 _CurrentObsList.clear();
1051 }
1052 return decoded;
1053}
1054
1055//
1056////////////////////////////////////////////////////////////////////////////
1057bool RTCM3Decoder::DecodeGPSEphemeris(unsigned char* data, int size) {
1058 bool decoded = false;
1059
1060 if (size == 67) {
1061 t_ephGPS eph;
1062 int i, week;
1063 uint64_t numbits = 0, bitfield = 0;
1064 int fitIntervalFalg = 0;
1065
1066 data += 3; /* header */
1067 size -= 6; /* header + crc */
1068 SKIPBITS(12)
1069
1070 eph._receptDateTime = currentDateAndTimeGPS();
1071 eph._receptStaID = _staID;
1072
1073 GETBITS(i, 6)
1074 if (i < 1 || i > 63 ) {
1075#ifdef BNC_DEBUG_BCE
1076 emit(newMessage(QString("%1: Block %2 (G) PRN# is out of range: %3!")
1077 .arg(_staID)
1078 .arg(1019,4)
1079 .arg(i).toLatin1(), true));
1080#endif
1081 return false;
1082 }
1083 eph._prn.set('G', i);
1084 checkPrnRange(eph._prn);
1085 GETBITS(week, 10)
1086 if (week < 0 || week > 1023) {
1087#ifdef BNC_DEBUG_BCE
1088 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1089 .arg(_staID)
1090 .arg(1019,4)
1091 .arg(eph._prn.toString().c_str())
1092 .arg(week).toLatin1(), true));
1093#endif
1094 return false;
1095 }
1096 GETBITS(i, 4)
1097 eph._ura = accuracyFromIndex(i, eph.system());
1098 GETBITS(eph._L2Codes, 2)
1099 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1100 GETBITS(eph._IODE, 8)
1101 GETBITS(i, 16)
1102 i <<= 4;
1103 if (i < 0 || i > 604784) {
1104#ifdef BNC_DEBUG_BCE
1105 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1106 .arg(_staID)
1107 .arg(1019,4)
1108 .arg(eph._prn.toString().c_str())
1109 .arg(i).toLatin1(), true));
1110#endif
1111 return false;
1112 }
1113 eph._TOC.set(i * 1000);
1114 GETFLOATSIGN(eph._clock_driftrate, 8, 1.0 / (double )(1 << 30) / (double )(1 << 25))
1115 GETFLOATSIGN(eph._clock_drift, 16, 1.0 / (double )(1 << 30) / (double )(1 << 13))
1116 GETFLOATSIGN(eph._clock_bias, 22, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1117 GETBITS(eph._IODC, 10)
1118 GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
1119 GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
1120 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1121 GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
1122 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1123 GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
1124 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
1125 if (eph._sqrt_A < 1000.0) {
1126#ifdef BNC_DEBUG_BCE
1127 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1128 .arg(_staID).arg(1019,4).arg(eph._prn.toString().c_str())
1129 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
1130#endif
1131 return false;
1132 }
1133 GETBITS(i, 16)
1134 i <<= 4;
1135 if (i < 0 || i > 604784) {
1136#ifdef BNC_DEBUG_BCE
1137 emit(newMessage(QString("%1: Block %2 (%3) TOE is out of range: %4!")
1138 .arg(_staID)
1139 .arg(1019,4)
1140 .arg(eph._prn.toString().c_str())
1141 .arg(i).toLatin1(), true));
1142#endif
1143 return false;
1144 }
1145 eph._TOEsec = i;
1146 bncTime t;
1147 t.set(i * 1000);
1148 eph._TOEweek = t.gpsw();
1149 int numOfRollOvers = int(floor(t.gpsw()/1024.0));
1150 week += (numOfRollOvers * 1024);
1151 /* week from HOW, differs from TOC, TOE week, we use adapted value instead */
1152 if (eph._TOEweek > week + 1 || eph._TOEweek < week - 1) /* invalid week */
1153 return false;
1154 GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
1155 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1156 GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
1157 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1158 GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
1159 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1160 GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
1161 GETFLOATSIGN(eph._TGD, 8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1162 GETBITS(eph._health, 6)
1163 GETBITS(eph._L2PFlag, 1)
1164 GETBITS(fitIntervalFalg, 1)
1165 eph._fitInterval = fitIntervalFromFlag(fitIntervalFalg, eph._IODC, eph.system());
1166 eph._TOT = 0.9999e9;
1167 eph._type = t_eph::LNAV;
1168 eph._prn.setFlag(eph._type);
1169
1170 emit newGPSEph(eph);
1171 decoded = true;
1172 }
1173 return decoded;
1174}
1175
1176//
1177////////////////////////////////////////////////////////////////////////////
1178bool RTCM3Decoder::DecodeGLONASSEphemeris(unsigned char* data, int size) {
1179 bool decoded = false;
1180
1181 if (size == 51) {
1182 t_ephGlo eph;
1183 int sv, i, tk;
1184 uint64_t numbits = 0, bitfield = 0;
1185
1186 data += 3; /* header */
1187 size -= 6; /* header + crc */
1188 SKIPBITS(12)
1189
1190 eph._receptDateTime = currentDateAndTimeGPS();
1191 eph._receptStaID = _staID;
1192
1193 GETBITS(sv, 6)
1194 if (sv < 1 || sv > 63) {
1195#ifdef BNC_DEBUG_BCE
1196 emit(newMessage(QString("%1: Block %2 (R): SLOT# is unknown (0) or out of range: %3!")
1197 .arg(_staID)
1198 .arg(1020,4)
1199 .arg(sv).toLatin1(), true));
1200#endif
1201 return false;
1202 }
1203 eph._prn.set('R', sv);
1204 checkPrnRange(eph._prn);
1205
1206 GETBITS(i, 5)
1207 if (i < 0 || i > 20) {
1208#ifdef BNC_DEBUG_BCE
1209 emit(newMessage(QString("%1: Block %2 (%3): FRQ CHN# is out of range: %4")
1210 .arg(_staID)
1211 .arg(1020,4)
1212 .arg(eph._prn.toString().c_str())
1213 .arg(i).toLatin1(), true));
1214#endif
1215 return false;
1216 }
1217 eph._frq_num = i - 7;
1218 GETBITS(eph._almanac_health, 1) /* almanac healthy */
1219 GETBITS(eph._almanac_health_availablility_indicator, 1) /* almanac health ok */
1220 GETBITS(eph._P1, 2) /* P1 */
1221 /* tk */
1222 GETBITS(i, 5)
1223 if (i < 0 || i > 23) {
1224#ifdef BNC_DEBUG_BCE
1225 emit(newMessage(QString("%1: Block %2 (%3): T_k (bits 11-7) is out of range: %4")
1226 .arg(_staID)
1227 .arg(1020,4)
1228 .arg(eph._prn.toString().c_str())
1229 .arg(i).toLatin1(), true));
1230#endif
1231 return false;
1232 }
1233 tk = i * 60 * 60;
1234 GETBITS(i, 6)
1235 if (i < 0 || i > 59) {
1236#ifdef BNC_DEBUG_BCE
1237 emit(newMessage(QString("%1: Block %2 (%3): T_k (bits 6-1) is out of range: %4")
1238 .arg(_staID)
1239 .arg(1020,4)
1240 .arg(eph._prn.toString().c_str())
1241 .arg(i).toLatin1(), true));
1242#endif
1243 return false;
1244 }
1245 tk += i * 60;
1246 GETBITS(i, 1)
1247 if (i < 0 || i > 1) {
1248#ifdef BNC_DEBUG_BCE
1249 emit(newMessage(QString("%1: Block %2 (%3): T_k (bit 0) is out of range: %4")
1250 .arg(_staID)
1251 .arg(1020,4)
1252 .arg(eph._prn.toString().c_str())
1253 .arg(i).toLatin1(), true));
1254#endif
1255 return false;
1256 }
1257 tk += i * 30;
1258 eph._tki = tk - 3*60*60;
1259 if(eph._tki < 0.0) {
1260 eph._tki += 86400.0;
1261 }
1262 GETBITS(eph._health, 1) /* MSB of Bn*/
1263 GETBITS(eph._P2, 1) /* P2 */
1264 GETBITS(i, 7)
1265 i *= 15;
1266 if (i < 15 || i > 1425) {
1267#ifdef BNC_DEBUG_BCE
1268 emit(newMessage(QString("%1: Block %2 (%3): T_b is out of range: %4")
1269 .arg(_staID)
1270 .arg(1020,4)
1271 .arg(eph._prn.toString().c_str())
1272 .arg(i).toLatin1(), true));
1273#endif
1274 return false;
1275 }
1276 eph._TOC.setTk(i * 60 * 1000); /* tb */
1277
1278 GETFLOATSIGNM(eph._x_vel, 24, 1.0 / (double )(1 << 20))
1279 GETFLOATSIGNM(eph._x_pos, 27, 1.0 / (double )(1 << 11))
1280 GETFLOATSIGNM(eph._x_acc, 5, 1.0 / (double )(1 << 30))
1281 GETFLOATSIGNM(eph._y_vel, 24, 1.0 / (double )(1 << 20))
1282 GETFLOATSIGNM(eph._y_pos, 27, 1.0 / (double )(1 << 11))
1283 GETFLOATSIGNM(eph._y_acc, 5, 1.0 / (double )(1 << 30))
1284 GETFLOATSIGNM(eph._z_vel, 24, 1.0 / (double )(1 << 20))
1285 GETFLOATSIGNM(eph._z_pos, 27, 1.0 / (double )(1 << 11))
1286 GETFLOATSIGNM(eph._z_acc, 5, 1.0 / (double )(1 << 30))
1287 GETBITS(eph._P3, 1) /* P3 */
1288 GETFLOATSIGNM(eph._gamma, 11, 1.0 / (double )(1 << 30) / (double )(1 << 10))
1289 GETBITS(eph._M_P, 2) /* GLONASS-M P, */
1290 GETBITS(eph._M_l3, 1) /* GLONASS-M ln (third string) */
1291 GETFLOATSIGNM(eph._tau, 22, 1.0 / (double )(1 << 30)) /* GLONASS tau n(tb) */
1292 GETFLOATSIGNM(eph._M_delta_tau, 5, 1.0 / (double )(1 << 30)) /* GLONASS-M delta tau n(tb) */
1293 GETBITS(eph._E, 5)
1294 GETBITS(eph._M_P4, 1) /* GLONASS-M P4 */
1295 GETBITS(eph._M_FT, 4) /* GLONASS-M Ft */
1296 GETBITS(eph._M_NT, 11) /* GLONASS-M Nt */
1297 if (eph._M_NT == 0.0) {
1298#ifdef BNC_DEBUG_BCE
1299 emit(newMessage(QString("%1: Block %2 (%3): NT = %4: missing data!")
1300 .arg(_staID).arg(1020,4).arg(eph._prn.toString().c_str()).arg(eph._M_NT,4).toLatin1(), true));
1301#endif
1302 return false;
1303 }
1304 GETBITS(eph._M_M, 2) /* GLONASS-M M */
1305 GETBITS(eph._additional_data_availability, 1) /* GLONASS-M The Availability of Additional Data */
1306 if (eph._additional_data_availability == 0.0) {
1307#ifdef BNC_DEBUG_BCE
1308 emit(newMessage(QString("%1: Block %2 (%3): ADD = %4: missing data!")
1309 .arg(_staID).arg(1020,4).arg(eph._prn.toString().c_str())
1310 .arg(eph._additional_data_availability).toLatin1(), true));
1311#endif
1312 return false;
1313 }
1314 GETBITS(eph._M_NA, 11) /* GLONASS-M Na */
1315 GETFLOATSIGNM(eph._tauC, 32, 1.0/(double)(1<<30)/(double)(1<<1)) /* GLONASS tau c */
1316 GETBITS(eph._M_N4, 5) /* GLONASS-M N4 */
1317 GETFLOATSIGNM(eph._M_tau_GPS, 22, 1.0/(double)(1<<30)) /* GLONASS-M tau GPS */
1318 GETBITS(eph._M_l5, 1) /* GLONASS-M ln (fifth string) */
1319
1320 unsigned year, month, day;
1321 eph._TOC.civil_date(year, month, day);
1322 eph._gps_utc = gnumleap(year, month, day);
1323 eph._tt = eph._TOC;
1324
1325 eph._xv(1) = eph._x_pos * 1.e3;
1326 eph._xv(2) = eph._y_pos * 1.e3;
1327 eph._xv(3) = eph._z_pos * 1.e3;
1328 if (eph._xv.Rows(1,3).NormFrobenius() < 1.0) {
1329#ifdef BNC_DEBUG_BCE
1330 emit(newMessage(QString("%1: Block %2 (%3): zero position!")
1331 .arg(_staID).arg(1020,4).arg(eph._prn.toString().c_str()).toLatin1(), true));
1332#endif
1333 return false;
1334 }
1335 eph._xv(4) = eph._x_vel * 1.e3;
1336 eph._xv(5) = eph._y_vel * 1.e3;
1337 eph._xv(6) = eph._z_vel * 1.e3;
1338 if (eph._xv.Rows(4,6).NormFrobenius() < 1.0) {
1339#ifdef BNC_DEBUG_BCE
1340 emit(newMessage(QString("%1: Block %2 (%3): zero velocity!")
1341 .arg(_staID).arg(1020,4).arg(eph._prn.toString().c_str()).toLatin1(), true));
1342#endif
1343 return false;
1344 }
1345 GLOFreq[sv - 1] = 100 + eph._frq_num ; /* store frequency for other users (MSM) */
1346 _gloFrq = QString("%1 %2").arg(eph._prn.toString().c_str()).arg(eph._frq_num, 2, 'f', 0);
1347
1348 if (eph.validMdata()) {
1349 eph._type = t_eph::FDMA_M;
1350 }
1351 else {
1352 eph._type = t_eph::FDMA;
1353 }
1354 eph._prn.setFlag(eph._type);
1355 eph._healthflags_unknown = false;
1356 eph._statusflags_unknown = false;
1357
1358 emit newGlonassEph(eph);
1359 decoded = true;
1360 }
1361 return decoded;
1362}
1363
1364//
1365////////////////////////////////////////////////////////////////////////////
1366bool RTCM3Decoder::DecodeQZSSEphemeris(unsigned char* data, int size) {
1367 bool decoded = false;
1368
1369 if (size == 67) {
1370 t_ephGPS eph;
1371 int i, week;
1372 uint64_t numbits = 0, bitfield = 0;
1373 int fitIntervalFalg = 0;
1374
1375 data += 3; /* header */
1376 size -= 6; /* header + crc */
1377 SKIPBITS(12)
1378
1379 eph._receptDateTime = currentDateAndTimeGPS();
1380 eph._receptStaID = _staID;
1381
1382 GETBITS(i, 4)
1383 if (i < 1 || i > 10 ) {
1384#ifdef BNC_DEBUG_BCE
1385 emit(newMessage(QString("%1: Block %2 (J) SAT ID is out of range: %3!")
1386 .arg(_staID)
1387 .arg(1044,4)
1388 .arg(i).toLatin1(), true));
1389#endif
1390 return false;
1391 }
1392 eph._prn.set('J', i);
1393 checkPrnRange(eph._prn);
1394
1395 GETBITS(i, 16)
1396 i <<= 4;
1397 if (i < 0 || i > 604784) {
1398#ifdef BNC_DEBUG_BCE
1399 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1400 .arg(_staID)
1401 .arg(1044,4)
1402 .arg(eph._prn.toString().c_str())
1403 .arg(i).toLatin1(), true));
1404#endif
1405 return false;
1406 }
1407 eph._TOC.set(i * 1000);
1408
1409 GETFLOATSIGN(eph._clock_driftrate, 8, 1.0 / (double )(1 << 30) / (double )(1 << 25))
1410 GETFLOATSIGN(eph._clock_drift, 16, 1.0 / (double )(1 << 30) / (double )(1 << 13))
1411 GETFLOATSIGN(eph._clock_bias, 22, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1412 GETBITS(eph._IODE, 8)
1413 GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
1414 GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
1415 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1416 GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
1417 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1418 GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
1419 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
1420 if (eph._sqrt_A < 1000.0) {
1421#ifdef BNC_DEBUG_BCE
1422 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1423 .arg(_staID).arg(1044,4).arg(eph._prn.toString().c_str())
1424 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
1425#endif
1426 return false;
1427 }
1428 GETBITS(i, 16)
1429 i <<= 4;
1430 if (i < 0 || i > 604784) {
1431#ifdef BNC_DEBUG_BCE
1432 emit(newMessage(QString("%1: Block %2 (%3) TOE is out of range: %4!")
1433 .arg(_staID)
1434 .arg(1044,4)
1435 .arg(eph._prn.toString().c_str())
1436 .arg(i).toLatin1(), true));
1437#endif
1438 return false;
1439 }
1440 eph._TOEsec = i;
1441 bncTime t;
1442 t.set(i*1000);
1443 eph._TOEweek = t.gpsw();
1444 GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
1445 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1446 GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
1447 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1448 GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
1449 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1450 GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
1451 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1452 GETBITS(eph._L2Codes, 2)
1453 GETBITS(week, 10)
1454 if (week < 0 || week > 1023) {
1455#ifdef BNC_DEBUG_BCE
1456 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1457 .arg(_staID)
1458 .arg(1044,4)
1459 .arg(eph._prn.toString().c_str())
1460 .arg(week).toLatin1(), true));
1461#endif
1462 return false;
1463 }
1464 int numOfRollOvers = int(floor(t.gpsw()/1024.0));
1465 week += (numOfRollOvers * 1024);
1466 /* week from HOW, differs from TOC, TOE week, we use adapted value instead */
1467 if (eph._TOEweek > week + 1 || eph._TOEweek < week - 1) /* invalid week */
1468 return false;
1469
1470 GETBITS(i, 4)
1471 eph._ura = accuracyFromIndex(i, eph.system());
1472 GETBITS(eph._health, 6)
1473 GETFLOATSIGN(eph._TGD, 8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1474 GETBITS(eph._IODC, 10)
1475 GETBITS(fitIntervalFalg, 1)
1476 eph._fitInterval = fitIntervalFromFlag(fitIntervalFalg, eph._IODC, eph.system());
1477 eph._TOT = 0.9999e9;
1478 eph._type = t_eph::LNAV;
1479
1480 emit newGPSEph(eph);
1481 decoded = true;
1482 }
1483 return decoded;
1484}
1485
1486//
1487////////////////////////////////////////////////////////////////////////////
1488bool RTCM3Decoder::DecodeNavICEphemeris(unsigned char* data, int size) {
1489 bool decoded = false;
1490
1491 if (size == 67) {
1492 t_ephGPS eph;
1493 int i, week, L5Flag, SFlag;
1494 uint64_t numbits = 0, bitfield = 0;
1495
1496 data += 3; /* header */
1497 size -= 6; /* header + crc */
1498 SKIPBITS(12)
1499
1500 eph._receptDateTime = currentDateAndTimeGPS();
1501 eph._receptStaID = _staID;
1502
1503 GETBITS(i, 6)
1504 if (i < 1 || i > 63 ) {
1505#ifdef BNC_DEBUG_BCE
1506 emit(newMessage(QString("%1: Block %2 (I) PRN# is out of range: %3!")
1507 .arg(_staID)
1508 .arg(1041,4)
1509 .arg(i).toLatin1(), true));
1510#endif
1511 return false;
1512 }
1513 eph._prn.set('I', i);
1514 checkPrnRange(eph._prn);
1515 GETBITS(week, 10)
1516 if (week < 0 || week > 1023) {
1517#ifdef BNC_DEBUG_BCE
1518 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1519 .arg(_staID)
1520 .arg(1041,4)
1521 .arg(eph._prn.toString().c_str())
1522 .arg(week).toLatin1(), true));
1523#endif
1524 return false;
1525 }
1526 GETFLOATSIGN(eph._clock_bias, 22, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1527 GETFLOATSIGN(eph._clock_drift, 16, 1.0 / (double )(1 << 30) / (double )(1 << 13))
1528 GETFLOATSIGN(eph._clock_driftrate, 8, 1.0 / (double )(1 << 30) / (double )(1 << 25))
1529 GETBITS(i, 4)
1530 eph._ura = accuracyFromIndex(i, eph.system());
1531 GETBITS(i, 16)
1532 i <<= 4;
1533 if (i < 0 || i > 1048560) {
1534#ifdef BNC_DEBUG_BCE
1535 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1536 .arg(_staID)
1537 .arg(1041,4)
1538 .arg(eph._prn.toString().c_str())
1539 .arg(i).toLatin1(), true));
1540#endif
1541 return false;
1542 }
1543 eph._TOC.set(i * 1000);
1544 GETFLOATSIGN(eph._TGD, 8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1545 GETFLOATSIGN(eph._Delta_n, 22, R2R_PI/(double)(1<<30)/(double)(1 << 11))
1546 // IODCE
1547 GETBITS(eph._IODE, 8)
1548 eph._IODC = eph._IODE;
1549 SKIPBITS(10)
1550 GETBITS(L5Flag, 1)
1551 GETBITS(SFlag, 1)
1552 if (L5Flag == 0 && SFlag == 0) {
1553 eph._health = 0.0;
1554 }
1555 else if (L5Flag == 0 && SFlag == 1) {
1556 eph._health = 1.0;
1557 }
1558 else if (L5Flag == 1 && SFlag == 0) {
1559 eph._health = 2.0;
1560 }
1561 else if (L5Flag == 1 && SFlag == 1) {
1562 eph._health = 3.0;
1563 }
1564 GETFLOATSIGN(eph._Cuc, 15, 1.0 / (double )(1 << 28))
1565 GETFLOATSIGN(eph._Cus, 15, 1.0 / (double )(1 << 28))
1566 GETFLOATSIGN(eph._Cic, 15, 1.0 / (double )(1 << 28))
1567 GETFLOATSIGN(eph._Cis, 15, 1.0 / (double )(1 << 28))
1568 GETFLOATSIGN(eph._Crc, 15, 1.0 / (double )(1 << 4))
1569 GETFLOATSIGN(eph._Crs, 15, 1.0 / (double )(1 << 4))
1570 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1571 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
1572 GETBITS(i, 16)
1573 i <<= 4;
1574 if (i < 0 || i > 1048560) {
1575#ifdef BNC_DEBUG_BCE
1576 emit(newMessage(QString("%1: Block %2 (%3) TOE is out of range: %4!")
1577 .arg(_staID)
1578 .arg(1041,4)
1579 .arg(eph._prn.toString().c_str())
1580 .arg(i).toLatin1(), true));
1581#endif
1582 return false;
1583 }
1584 eph._TOEsec = i;
1585 bncTime t;
1586 t.set(i * 1000);
1587 eph._TOEweek = t.gpsw();
1588 int numOfRollOvers = int(floor(t.gpsw()/1024.0));
1589 week += (numOfRollOvers * 1024);
1590 /* week from HOW, differs from TOC, TOE week, we use adapted value instead */
1591 if (eph._TOEweek > week + 1 || eph._TOEweek < week - 1) /* invalid week */
1592 return false;
1593 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1594 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
1595 if (eph._sqrt_A < 1000.0) {
1596#ifdef BNC_DEBUG_BCE
1597 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1598 .arg(_staID).arg(1041,4).arg(eph._prn.toString().c_str())
1599 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
1600#endif
1601 return false;
1602 }
1603 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
1604 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
1605 GETFLOATSIGN(eph._OMEGADOT, 22, R2R_PI/(double)(1<<30)/(double)(1<<11))
1606 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
1607 GETBITS(eph._s_bits_after_IDOT, 2)
1608 GETBITS(eph._s_bits_after_i0, 2)
1609
1610 eph._TOT = 0.9999e9;
1611 eph._type = t_eph::LNAV;
1612 eph._prn.setFlag(eph._type);
1613
1614 emit newGPSEph(eph);
1615 decoded = true;
1616 }
1617 return decoded;
1618}
1619
1620//
1621////////////////////////////////////////////////////////////////////////////
1622bool RTCM3Decoder::DecodeSBASEphemeris(unsigned char* data, int size) {
1623 bool decoded = false;
1624
1625 if (size == 35) {
1626 t_ephSBAS eph;
1627 int i;
1628 eph._health = 0;
1629 uint64_t numbits = 0, bitfield = 0;
1630
1631 data += 3; /* header */
1632 size -= 6; /* header + crc */
1633 SKIPBITS(12)
1634
1635 eph._receptDateTime = currentDateAndTimeGPS();
1636 eph._receptStaID = _staID;
1637
1638 GETBITS(i, 6)
1639 if (i < 0 || i > 38 ) {
1640#ifdef BNC_DEBUG_BCE
1641 emit(newMessage(QString("%1: Block %2 (S) PRN# is out of range: %3!")
1642 .arg(_staID)
1643 .arg(1043,4)
1644 .arg(i).toLatin1(), true));
1645#endif
1646 return false;
1647 }
1648 eph._prn.set('S', 20 + i);
1649 checkPrnRange(eph._prn);
1650 GETBITS(eph._IODN, 8)
1651 GETBITS(i, 13)
1652 i <<= 4;
1653 if (i < 0 || i > 86384) {
1654#ifdef BNC_DEBUG_BCE
1655 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1656 .arg(_staID)
1657 .arg(1043,4)
1658 .arg(eph._prn.toString().c_str())
1659 .arg(i).toLatin1(), true));
1660#endif
1661 return false;
1662 }
1663 eph._TOC.setTOD(i * 1000);
1664 GETBITS(i, 4)
1665 int health = 0;
1666 if (i == 15) {
1667 health |= (1 << 5);
1668 // in this case it is recommended
1669 // to set the bits 0,1,2,3 to 1 (MT17health = 15)
1670 health |= (1 << 0);
1671 health |= (1 << 1);
1672 health |= (1 << 2);
1673 health |= (1 << 3);
1674 eph._health = double(health);
1675 }
1676 eph._ura = accuracyFromIndex(i, eph.system());
1677 GETFLOATSIGN(eph._x_pos, 30, 0.08)
1678 GETFLOATSIGN(eph._y_pos, 30, 0.08)
1679 GETFLOATSIGN(eph._z_pos, 25, 0.4)
1680 ColumnVector pos(3);
1681 pos(1) = eph._x_pos; pos(2) = eph._y_pos; pos(3) = eph._z_pos;
1682 if (pos.NormFrobenius() < 1.0) {
1683#ifdef BNC_DEBUG_BCE
1684 emit(newMessage(QString("%1: Block %2 (%3): zero position!")
1685 .arg(_staID).arg(1043,4).arg(eph._prn.toString().c_str()).toLatin1(), true));
1686#endif
1687 return false;
1688 }
1689 GETFLOATSIGN(eph._x_vel, 17, 0.000625)
1690 GETFLOATSIGN(eph._y_vel, 17, 0.000625)
1691 GETFLOATSIGN(eph._z_vel, 18, 0.004)
1692 GETFLOATSIGN(eph._x_acc, 10, 0.0000125)
1693 GETFLOATSIGN(eph._y_acc, 10, 0.0000125)
1694 GETFLOATSIGN(eph._z_acc, 10, 0.0000625)
1695 GETFLOATSIGN(eph._agf0, 12, 1.0 / (1 << 30) / (1 << 1))
1696 GETFLOATSIGN(eph._agf1, 8, 1.0 / (1 << 30) / (1 << 10))
1697
1698 eph._TOT = 0.9999E9;
1699
1700 eph._type = t_eph::SBASL1;
1701 eph._prn.setFlag(eph._type);
1702
1703 emit newSBASEph(eph);
1704 decoded = true;
1705 }
1706 return decoded;
1707}
1708
1709//
1710////////////////////////////////////////////////////////////////////////////
1711bool RTCM3Decoder::DecodeGalileoEphemeris(unsigned char* data, int size) {
1712 bool decoded = false;
1713 uint64_t numbits = 0, bitfield = 0;
1714 int i, week;
1715
1716 data += 3; /* header */
1717 size -= 6; /* header + crc */
1718 GETBITS(i, 12)
1719
1720 if ((i == 1046 && size == 61) ||
1721 (i == 1045 && size == 60)) {
1722 t_ephGal eph;
1723 eph._receptDateTime = currentDateAndTimeGPS();
1724 eph._receptStaID = _staID;
1725
1726 eph._inav = (i == 1046);
1727 eph._fnav = (i == 1045);
1728 GETBITS(i, 6)
1729 if (i < 1 || i > 36 ) { // max. constellation within I/NAV / F/NAV frames is 36
1730#ifdef BNC_DEBUG_BCE
1731 emit(newMessage(QString("%1: Block %2 (E) PRN# is out of range: %3!")
1732 .arg(_staID)
1733 .arg(mnum,4)
1734 .arg(i).toLatin1(), true));
1735#endif
1736 return false;
1737 }
1738 eph._prn.set('E', i, eph._inav ? t_eph::INAV : t_eph::FNAV);
1739 checkPrnRange(eph._prn);
1740
1741 GETBITS(week, 12) //FIXME: roll-over after week 4095!!
1742 if (week < 0 || week > 4095) {
1743#ifdef BNC_DEBUG_BCE
1744 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1745 .arg(_staID)
1746 .arg(mnum,4)
1747 .arg(eph._prn.toString().c_str())
1748 .arg(week).toLatin1(), true));
1749#endif
1750 return false;
1751 }
1752 eph._TOEweek = week;
1753 GETBITS(eph._IODnav, 10)
1754 GETBITS(i, 8)
1755 eph._SISA = accuracyFromIndex(i, eph.system());
1756 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1757 GETBITSFACTOR(i, 14, 60)
1758 if (i < 0 || i > 604740) {
1759#ifdef BNC_DEBUG_BCE
1760 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1761 .arg(_staID)
1762 .arg(mnum,4)
1763 .arg(eph._prn.toString().c_str())
1764 .arg(i).toLatin1(), true));
1765#endif
1766 return false;
1767 }
1768 eph._TOC.set(1024 + eph._TOEweek, i);// Period #2 = + 1 x 1024 (has to be determined)
1769 GETFLOATSIGN(eph._clock_driftrate, 6, 1.0 / (double )(1 << 30) / (double )(1 << 29))
1770 GETFLOATSIGN(eph._clock_drift, 21, 1.0 / (double )(1 << 30) / (double )(1 << 16))
1771 GETFLOATSIGN(eph._clock_bias, 31, 1.0 / (double )(1 << 30) / (double )(1 << 4))
1772 GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
1773 GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
1774 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1775 GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
1776 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1777 GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
1778 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
1779 GETBITSFACTOR(eph._TOEsec, 14, 60)
1780 if (i < 0 || i > 604740) {
1781#ifdef BNC_DEBUG_BCE
1782 emit(newMessage(QString("%1: Block %2 (%3) TOE is out of range: %4!")
1783 .arg(_staID)
1784 .arg(mnum,4)
1785 .arg(eph._prn.toString().c_str())
1786 .arg(i).toLatin1(), true));
1787#endif
1788 return false;
1789 }
1790 /* FIXME: overwrite value, copied from old code */
1791 //eph._TOEsec = eph._TOC.gpssec();
1792 GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
1793 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1794 GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
1795 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1796 GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
1797 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1798 GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
1799 GETFLOATSIGN(eph._BGD_1_5A, 10, 1.0 / (double )(1 << 30) / (double )(1 << 2))
1800 if (eph._inav) {
1801 eph._type = t_eph::INAV;
1802 /* set unused F/NAV values */
1803 eph._E5a_HS = 0.0;
1804 eph._E5a_DataInvalid = false;
1805
1806 GETFLOATSIGN(eph._BGD_1_5B, 10, 1.0 / (double )(1 << 30) / (double )(1 << 2))
1807 GETBITS(eph._E5b_HS, 2)
1808 GETBITS(eph._E5b_DataInvalid, 1)
1809 GETBITS(eph._E1B_HS, 2)
1810 GETBITS(eph._E1B_DataInvalid, 1)
1811 if (eph._E5b_HS != eph._E1B_HS) {
1812#ifdef BNC_DEBUG_BCE
1813 emit(newMessage(QString("%1: Block %2 (%3) SHS E5b %4 E1B %5: inconsistent health!")
1814 .arg(_staID).arg(1046,4).arg(eph._prn.toString().c_str())
1815 .arg(eph._E5b_HS).arg(eph._E1B_HS).toLatin1(), true));
1816#endif
1817 return false;
1818 }
1819 if ((eph._BGD_1_5A == 0.0 && fabs(eph._BGD_1_5B) > 1e-9) ||
1820 (eph._BGD_1_5B == 0.0 && fabs(eph._BGD_1_5A) > 1e-9)) {
1821#ifdef BNC_DEBUG_BCE
1822 emit(newMessage(QString("%1: Block %2 (%3) BGD_1_5a = %4 BGD_1_5b = %5: inconsistent BGD!")
1823 .arg(_staID).arg(1046,4).arg(eph._prn.toString().c_str())
1824 .arg(eph._BGD_1_5A,10,'E',3).arg(eph._BGD_1_5B,10,'E',3).toLatin1(), true));
1825#endif
1826 return false;
1827 }
1828 }
1829 else {
1830 eph._type = t_eph::FNAV;
1831 /* set unused I/NAV values */
1832 eph._BGD_1_5B = 0.0;
1833 eph._E5b_HS = 0.0;
1834 eph._E1B_HS = 0.0;
1835 eph._E1B_DataInvalid = false;
1836 eph._E5b_DataInvalid = false;
1837
1838 GETBITS(eph._E5a_HS, 2)
1839 GETBITS(eph._E5a_DataInvalid, 1)
1840 }
1841 eph._TOT = 0.9999e9;
1842
1843 if (eph._sqrt_A < 1000.0) {
1844#ifdef BNC_DEBUG_BCE
1845 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1846 .arg(_staID).arg(eph._inav? 1046 : 1045,4).arg(eph._prn.toString().c_str())
1847 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
1848#endif
1849 return false;
1850 }
1851
1852 emit newGalileoEph(eph);
1853 decoded = true;
1854 }
1855 return decoded;
1856}
1857
1858//
1859////////////////////////////////////////////////////////////////////////////
1860bool RTCM3Decoder::DecodeBDSEphemeris(unsigned char* data, int size) {
1861 bool decoded = false;
1862 const double iMaxGEO = 10.0 / 180.0 * M_PI;
1863
1864 if (size == 70) {
1865 t_ephBDS eph;
1866 int i, week;
1867 uint64_t numbits = 0, bitfield = 0;
1868
1869 data += 3; /* header */
1870 size -= 6; /* header + crc */
1871 SKIPBITS(12)
1872
1873 eph._receptDateTime = currentDateAndTimeGPS();
1874 eph._receptStaID = _staID;
1875
1876 GETBITS(i, 6)
1877 if (i < 1 || i > 63 ) {
1878#ifdef BNC_DEBUG_BCE
1879 emit(newMessage(QString("%1: Block %2 (C) PRN# is out of range: %3!")
1880 .arg(_staID)
1881 .arg(1042,4)
1882 .arg(i).toLatin1(), true));
1883#endif
1884 return false;
1885 }
1886 eph._prn.set('C', i);
1887 checkPrnRange(eph._prn);
1888
1889 GETBITS(week, 13)
1890 if (week < 0 || week > 8191) {
1891#ifdef BNC_DEBUG_BCE
1892 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1893 .arg(_staID)
1894 .arg(1042,4)
1895 .arg(eph._prn.toString().c_str())
1896 .arg(week).toLatin1(), true));
1897#endif
1898 return false;
1899 }
1900 eph._BDTweek = week;
1901 GETBITS(i, 4)
1902 eph._ura = accuracyFromIndex(i, eph.system());
1903 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1904 GETBITS(eph._AODE, 5)
1905 GETBITS(i, 17)
1906 i <<= 3;
1907 if (i < 0 || i > 604792) {
1908#ifdef BNC_DEBUG_BCE
1909 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1910 .arg(_staID)
1911 .arg(1042,4)
1912 .arg(eph._prn.toString().c_str())
1913 .arg(i).toLatin1(), true));
1914#endif
1915 return false;
1916 }
1917 eph._TOC.setBDS(eph._BDTweek, i);
1918 GETFLOATSIGN(eph._clock_driftrate, 11, 1.0 / (double )(1 << 30) / (double )(1 << 30) / (double )(1 << 6))
1919 GETFLOATSIGN(eph._clock_drift, 22, 1.0 / (double )(1 << 30) / (double )(1 << 20))
1920 GETFLOATSIGN(eph._clock_bias, 24, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1921 GETBITS(eph._AODC, 5)
1922 GETFLOATSIGN(eph._Crs, 18, 1.0 / (double )(1 << 6))
1923 GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
1924 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1925 GETFLOATSIGN(eph._Cuc, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1926 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1927 GETFLOATSIGN(eph._Cus, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1928 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
1929 if (eph._sqrt_A < 1000.0) {
1930#ifdef BNC_DEBUG_BCE
1931 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1932 .arg(_staID).arg(1042,4).arg(eph._prn.toString().c_str())
1933 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
1934#endif
1935 return false;
1936 }
1937 GETBITS(i, 17)
1938 i <<= 3;
1939 if (i < 0 || i > 604792) {
1940#ifdef BNC_DEBUG_BCE
1941 emit(newMessage(QString("%1: Block %2 (%3) TOE is out of range: %4!")
1942 .arg(_staID)
1943 .arg(1042,4)
1944 .arg(eph._prn.toString().c_str())
1945 .arg(i).toLatin1(), true));
1946#endif
1947 return false;
1948 }
1949 eph._TOEsec = i;
1950 eph._TOE.setBDS(eph._BDTweek, i);
1951 GETFLOATSIGN(eph._Cic, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1952 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1953 GETFLOATSIGN(eph._Cis, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1954 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1955 GETFLOATSIGN(eph._Crc, 18, 1.0 / (double )(1 << 6))
1956 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1957 GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
1958 GETFLOATSIGN(eph._TGD1, 10, 0.0000000001)
1959 GETFLOATSIGN(eph._TGD2, 10, 0.0000000001)
1960 GETBITS(eph._SatH1, 1)
1961
1962 eph._TOT = 0.9999E9;
1963 if (eph._i0 > iMaxGEO) {
1964 eph._type = t_eph::D1;
1965 }
1966 else {
1967 eph._type = t_eph::D2;
1968 }
1969 eph._prn.setFlag(eph._type);
1970
1971 emit newBDSEph(eph);
1972 decoded = true;
1973 }
1974 return decoded;
1975}
1976
1977//
1978////////////////////////////////////////////////////////////////////////////
1979bool RTCM3Decoder::DecodeAntennaReceiver(unsigned char* data, int size) {
1980 char *antenna;
1981 char *antserialnum;
1982 char *receiver;
1983 char *rec_firmware;
1984 char *recserialnum;
1985 int type;
1986 int antsernum = -1;
1987 int antnum = -1;
1988 int recnum = -1;
1989 int recsernum = -1;
1990 int recfirnum = -1;
1991 uint64_t numbits = 0, bitfield = 0;
1992
1993 data += 3; /* header*/
1994 size -= 6; /* header + crc */
1995
1996 GETBITS(type, 12)
1997 SKIPBITS(12) /* reference station ID */
1998 GETSTRING(antnum, antenna)
1999 if ((antnum > -1 && antnum < 265) &&
2000 (_antType.empty() || strncmp(_antType.back()._descriptor, antenna, recnum) != 0)) {
2001 _antType.push_back(t_antInfo());
2002 memcpy(_antType.back()._descriptor, antenna, antnum);
2003 _antType.back()._descriptor[antnum] = 0;
2004 }
2005 SKIPBITS(8) /* antenna setup ID */
2006 if (type == 1008 || type == 1033 ) {
2007 GETSTRING(antsernum, antserialnum)
2008 if ((antsernum > -1 && antsernum < 265)) {
2009 memcpy(_antType.back()._serialnumber, antserialnum, antsernum);
2010 _antType.back()._serialnumber[antsernum] = 0;
2011 }
2012 }
2013
2014 if (type == 1033) {
2015 GETSTRING(recnum, receiver)
2016 GETSTRING(recfirnum, rec_firmware)
2017 GETSTRING(recsernum, recserialnum)
2018 if ((recnum > -1 && recnum < 265) &&
2019 (_recType.empty() || strncmp(_recType.back()._descriptor, receiver, recnum) != 0)) {
2020 _recType.push_back(t_recInfo());
2021 memcpy(_recType.back()._descriptor, receiver, recnum);
2022 _recType.back()._descriptor[recnum] = 0;
2023 if (recfirnum > -1 && recfirnum < 265) {
2024 memcpy(_recType.back()._firmware, rec_firmware, recfirnum);
2025 _recType.back()._firmware[recfirnum] = 0;
2026 }
2027 if (recsernum > -1 && recsernum < 265) {
2028 memcpy(_recType.back()._serialnumber, recserialnum, recsernum);
2029 _recType.back()._serialnumber[recsernum] = 0;
2030 }
2031 }
2032 }
2033 return true;
2034}
2035
2036//
2037////////////////////////////////////////////////////////////////////////////
2038bool RTCM3Decoder::DecodeAntennaPosition(unsigned char* data, int size) {
2039 int type;
2040 uint64_t numbits = 0, bitfield = 0;
2041 double x, y, z;
2042
2043 data += 3; /* header */
2044 size -= 6; /* header + crc */
2045
2046 GETBITS(type, 12)
2047 _antList.push_back(t_antRefPoint());
2048 _antList.back()._type = t_antRefPoint::ARP;
2049 SKIPBITS(22)
2050 GETBITSSIGN(x, 38)
2051 _antList.back()._xx = x * 1e-4;
2052 SKIPBITS(2)
2053 GETBITSSIGN(y, 38)
2054 _antList.back()._yy = y * 1e-4;
2055 SKIPBITS(2)
2056 GETBITSSIGN(z, 38)
2057 _antList.back()._zz = z * 1e-4;
2058 if (type == 1006) {
2059 double h;
2060 GETBITS(h, 16)
2061 _antList.back()._height = h * 1e-4;
2062 _antList.back()._height_f = true;
2063 }
2064 _antList.back()._message = type;
2065
2066 return true;
2067}
2068
2069//
2070////////////////////////////////////////////////////////////////////////////
2071bool RTCM3Decoder::DecodeGLONASSCodePhaseBiases(unsigned char* data, int size) {
2072 t_GloBiasInfo gloBiasInfo;
2073 int i = 0;
2074 uint64_t numbits = 0, bitfield = 0;
2075
2076 data += 3; // header
2077 size -= 6; // header + crc
2078
2079 SKIPBITS(12) // Message Number
2080 GETBITS(gloBiasInfo._staID, 12)
2081 GETBITS(gloBiasInfo._indicator, 1) // 0.. not aligned, 1.. aligned
2082 SKIPBITS(3) // reserved bits
2083 unsigned int bitmask;
2084 GETBITS(bitmask, 4)
2085 bool L1C_valid = bitExtracted(unsigned(bitmask), 1, 0);
2086 bool L1P_valid = bitExtracted(unsigned(bitmask), 1, 1);
2087 bool L2C_valid = bitExtracted(unsigned(bitmask), 1, 2);
2088 bool L2P_valid = bitExtracted(unsigned(bitmask), 1, 3);
2089
2090 if (L1C_valid) {
2091 GETBITSSIGN(i, 16)
2092 gloBiasInfo._L1C_value = i * 0.02;
2093 }
2094 if (L1P_valid) {
2095 GETBITSSIGN(i, 16)
2096 gloBiasInfo._L1P_value = i * 0.02;
2097 }
2098 if (L2C_valid) {
2099 GETBITSSIGN(i, 16)
2100 gloBiasInfo._L2C_value = i * 0.02;
2101 }
2102 if (L2P_valid) {
2103 GETBITSSIGN(i, 16)
2104 gloBiasInfo._L2P_value = i * 0.02;
2105 }
2106
2107 if (_gloBiasInfo != gloBiasInfo) {
2108 _gloBiasInfo.set(gloBiasInfo);
2109 }
2110 return true;
2111}
2112
2113//
2114////////////////////////////////////////////////////////////////////////////
2115bool RTCM3Decoder::DecodeServiceCRS(unsigned char* data, int size) {
2116 t_serviceCrs serviceCrs;
2117 int servicecrsnum = -1;
2118
2119 uint64_t numbits = 0, bitfield = 0;
2120
2121 data += 3; // header
2122 size -= 6; // header + crc
2123
2124 SKIPBITS(12) // Message Number
2125
2126 GETBITS(servicecrsnum, 5)
2127 if (servicecrsnum > -1 && servicecrsnum <= 31) {
2128 for(int i = 0; i < servicecrsnum; i++) {
2129 GETBITS(serviceCrs._name[i], 8);
2130 }
2131 serviceCrs._name[servicecrsnum] = 0;
2132 }
2133 if (_serviceCrs.empty() ||
2134 (strncmp(_serviceCrs.back()._name, serviceCrs._name, servicecrsnum) != 0)) {
2135 _serviceCrs.push_back(serviceCrs);
2136 GETFLOAT(_serviceCrs.back()._CE, 16, 1/100.0)
2137 _serviceCrs.back().setCoordinateEpochFromCE();
2138 //_serviceCrs.back().print();
2139 }
2140 return true;
2141
2142}
2143
2144//
2145////////////////////////////////////////////////////////////////////////////
2146bool RTCM3Decoder::DecodeRTCMCRS(unsigned char* data, int size) {
2147
2148 t_rtcmCrs rtcmCrs;
2149 int rtcmcrsnum = -1;
2150
2151 uint64_t numbits = 0, bitfield = 0;
2152
2153 data += 3; // header
2154 size -= 6; // header + crc
2155
2156 SKIPBITS(12) // Message Number
2157 GETBITS(rtcmcrsnum, 5)
2158 if (rtcmcrsnum > -1 && rtcmcrsnum <= 31) {
2159 for(int i = 0; i < rtcmcrsnum; i++) {
2160 GETBITS(rtcmCrs._name[i], 8);
2161 }
2162 rtcmCrs._name[rtcmcrsnum] = 0;
2163 }
2164 if (_rtcmCrs.empty() ||
2165 (strncmp(_rtcmCrs.back()._name, rtcmCrs._name, rtcmcrsnum) != 0)) {
2166 _rtcmCrs.push_back(rtcmCrs);
2167
2168 GETBITS(_rtcmCrs.back()._anchor, 1)
2169 GETBITS(_rtcmCrs.back()._plateNumber, 5)
2170
2171 int dblinksnum = 0;
2172 GETBITS(dblinksnum, 3)
2173 for (int i = 0; i < dblinksnum; i++) {
2174 int dblinknum = -1;
2175 char dblinkname[31];
2176 GETBITS(dblinknum, 5)
2177 if (dblinknum > -1 && dblinknum <= 31) {
2178 for(int i = 0; i < dblinknum; i++) {
2179 GETBITS(dblinkname[i], 8);
2180 }
2181 dblinkname[dblinknum] = 0;
2182 _rtcmCrs.back()._databaseLinks.append(QString("%1").arg(dblinkname));
2183 }
2184 }
2185 //_rtcmCrs.back().print();
2186 }
2187
2188 return true;
2189}
2190
2191
2192////////////////////////////////////////////////////////////////////////////
2193bool RTCM3Decoder::DecodeHelmertTrafoParameters(unsigned char* data, int size) {
2194
2195 t_helmertPar helmertPar;
2196 int sourcenum = -1;
2197 int targetnum = -1;
2198
2199 uint64_t numbits = 0, bitfield = 0;
2200 data += 3; // header
2201 size -= 6; // header + crc
2202
2203 SKIPBITS(12) // Message Number
2204 GETBITS(sourcenum, 5)
2205 if (sourcenum > -1 && sourcenum <= 31) {
2206 for(int i = 0; i < sourcenum; i++) {
2207 GETBITS(helmertPar._sourceName[i], 8);
2208 }
2209 helmertPar._sourceName[sourcenum] = 0;
2210 }
2211 GETBITS(targetnum, 5)
2212 if (targetnum > -1 && targetnum <= 31) {
2213 for(int i = 0; i < targetnum; i++) {
2214 GETBITS(helmertPar._targetName[i], 8);
2215 }
2216 helmertPar._targetName[targetnum] = 0;
2217 }
2218 GETBITS(helmertPar._sysIdentNum, 8)
2219 GETBITS(helmertPar._utilTrafoMessageIndicator, 10)
2220 GETBITS(helmertPar._mjd, 16)
2221 helmertPar._mjd += 44244;
2222
2223 // delete old parameter entries if available
2224 if (!_helmertPar.empty()) {
2225 QList<t_helmertPar>::iterator it = _helmertPar.begin();
2226 while (it != _helmertPar.end()) {
2227 (helmertPar == *it) ? it = _helmertPar.erase(it) : ++it;
2228 }
2229 }
2230 _helmertPar.push_back(helmertPar);
2231
2232 GETFLOATSIGN(_helmertPar.back()._dx, 23, 1/1000.0)
2233 GETFLOATSIGN(_helmertPar.back()._dy, 23, 1/1000.0)
2234 GETFLOATSIGN(_helmertPar.back()._dz, 23, 1/1000.0)
2235
2236 GETFLOATSIGN(_helmertPar.back()._ox, 32, 1/50000.0)
2237 GETFLOATSIGN(_helmertPar.back()._oy, 32, 1/50000.0)
2238 GETFLOATSIGN(_helmertPar.back()._oz, 32, 1/50000.0)
2239
2240 GETFLOATSIGN(_helmertPar.back()._sc, 25, 1/100000.0)
2241
2242 GETFLOATSIGN(_helmertPar.back()._dxr, 17, 1/50000.0)
2243 GETFLOATSIGN(_helmertPar.back()._dyr, 17, 1/50000.0)
2244 GETFLOATSIGN(_helmertPar.back()._dzr, 17, 1/50000.0)
2245
2246 GETFLOATSIGN(_helmertPar.back()._oxr, 17, 1/2500000.0)
2247 GETFLOATSIGN(_helmertPar.back()._oyr, 17, 1/2500000.0)
2248 GETFLOATSIGN(_helmertPar.back()._ozr, 17, 1/2500000.0)
2249
2250 GETFLOATSIGN(_helmertPar.back()._scr, 14, 1/5000000.0)
2251
2252 //_helmertPar.back().print();
2253
2254 return true;
2255}
2256
2257
2258//
2259////////////////////////////////////////////////////////////////////////////
2260t_irc RTCM3Decoder::Decode(char* buffer, int bufLen, vector<string>& errmsg) {
2261 bool decoded = false;
2262
2263 errmsg.clear();
2264
2265 while (bufLen && _MessageSize < sizeof(_Message)) {
2266 int l = sizeof(_Message) - _MessageSize;
2267 if (l > bufLen)
2268 l = bufLen;
2269 memcpy(_Message + _MessageSize, buffer, l);
2270 _MessageSize += l;
2271 bufLen -= l;
2272 buffer += l;
2273 int id;
2274 while ((id = GetMessage())) {
2275 /* reset station ID for file loading as it can change */
2276 if (_rawFile)
2277 _staID = _rawFile->staID();
2278 /* store the id and message size into the list of loaded blocks */
2279 _typeList.push_back(t_typeInfo());
2280 _typeList.back()._type = id;
2281 _typeList.back()._size = _BlockSize -6; /* header + crc */
2282
2283 /* SSR I+II data handled in another function, already pass the
2284 * extracted data block. That does no harm, as it anyway skip everything
2285 * else. */
2286 if ((id >= 1057 && id <= 1068) ||
2287 (id >= 1240 && id <= 1270) ||
2288// (id > 0 && id <= 100) ||
2289 (id == 4076)) {
2290 if (!_coDecoders.contains(_staID.toLatin1())) {
2291 _coDecoders[_staID.toLatin1()] = new RTCM3coDecoder(_staID);
2292 if (id == 4076) {
2293 _coDecoders[_staID.toLatin1()]->initSsrFormatType(RTCM3coDecoder::IGSssr);
2294 }
2295 else {
2296// _coDecoders[_staID.toLatin1()]->initSsrFormatType(RTCM3coDecoder::RTCMnewssr);
2297 _coDecoders[_staID.toLatin1()]->initSsrFormatType(RTCM3coDecoder::RTCMssr);
2298 }
2299 }
2300 RTCM3coDecoder* coDecoder = _coDecoders[_staID.toLatin1()];
2301 if (coDecoder->Decode(reinterpret_cast<char *>(_Message), _BlockSize, errmsg) == success) {
2302 decoded = true;
2303 }
2304 }
2305 else if (id >= 1070 && id <= 1137) { /* MSM */
2306 if (DecodeRTCM3MSM(_Message, _BlockSize))
2307 decoded = true;
2308 }
2309 else {
2310 switch (id) {
2311 case 1001:
2312 case 1003:
2313#ifdef BNC_DEBUG_OBS
2314 emit(newMessage(QString("%1: Block %2 contain partial data! Ignored!")
2315 .arg(_staID).arg(id).toLatin1(), true));
2316#endif
2317 break; /* no use decoding partial data ATM, remove break when data can be used */
2318 case 1002:
2319 case 1004:
2320 if (DecodeRTCM3GPS(_Message, _BlockSize))
2321 decoded = true;
2322 break;
2323 case 1009:
2324 case 1011:
2325#ifdef BNC_DEBUG_OBS
2326 emit(newMessage(QString("%1: Block %2 contain partial data! Ignored!")
2327 .arg(_staID).arg(id).toLatin1(), true));
2328#endif
2329 break; /* no use decoding partial data ATM, remove break when data can be used */
2330 case 1010:
2331 case 1012:
2332 if (DecodeRTCM3GLONASS(_Message, _BlockSize))
2333 decoded = true;
2334 break;
2335 case 1019:
2336 if (DecodeGPSEphemeris(_Message, _BlockSize))
2337 decoded = true;
2338 break;
2339 case 1020:
2340 if (DecodeGLONASSEphemeris(_Message, _BlockSize))
2341 decoded = true;
2342 break;
2343 case 1043:
2344 if (DecodeSBASEphemeris(_Message, _BlockSize))
2345 decoded = true;
2346 break;
2347 case 1044:
2348 if (DecodeQZSSEphemeris(_Message, _BlockSize))
2349 decoded = true;
2350 break;
2351 case 1041:
2352 if (DecodeNavICEphemeris(_Message, _BlockSize))
2353 decoded = true;
2354 break;
2355 case 1045:
2356 case 1046:
2357 if (DecodeGalileoEphemeris(_Message, _BlockSize))
2358 decoded = true;
2359 break;
2360 case 1042:
2361 if (DecodeBDSEphemeris(_Message, _BlockSize))
2362 decoded = true;
2363 break;
2364 case 1007:
2365 case 1008:
2366 case 1033:
2367 DecodeAntennaReceiver(_Message, _BlockSize);
2368 break;
2369 case 1005:
2370 case 1006:
2371 DecodeAntennaPosition(_Message, _BlockSize);
2372 break;
2373 case 1230:
2374 DecodeGLONASSCodePhaseBiases(_Message, _BlockSize);
2375 break;
2376 case 1300:
2377 DecodeServiceCRS(_Message, _BlockSize);
2378 break;
2379 case 1301:
2380 DecodeHelmertTrafoParameters(_Message, _BlockSize);
2381 break;
2382 case 1302:
2383 case 35:
2384 DecodeRTCMCRS(_Message, _BlockSize);
2385 break;
2386 }
2387 }
2388 }
2389 }
2390 /*
2391 for (int ii = 0; ii < _helmertParList.size(); ii++) {
2392 _helmertParList[ii].print();
2393 }*/
2394 return decoded ? success : failure;
2395}
2396
2397//
2398////////////////////////////////////////////////////////////////////////////
2399uint32_t RTCM3Decoder::CRC24(long size, const unsigned char *buf) {
2400 uint32_t crc = 0;
2401 int ii;
2402 while (size--) {
2403 crc ^= (*buf++) << (16);
2404 for (ii = 0; ii < 8; ii++) {
2405 crc <<= 1;
2406 if (crc & 0x1000000)
2407 crc ^= 0x01864cfb;
2408 }
2409 }
2410 return crc;
2411}
2412
2413//
2414////////////////////////////////////////////////////////////////////////////
2415int RTCM3Decoder::GetMessage(void) {
2416 unsigned char *m, *e;
2417 int i;
2418
2419 m = _Message + _SkipBytes;
2420 e = _Message + _MessageSize;
2421 _NeedBytes = _SkipBytes = 0;
2422 while (e - m >= 3) {
2423 if (m[0] == 0xD3) {
2424 _BlockSize = ((m[1] & 3) << 8) | m[2];
2425 if (e - m >= static_cast<int>(_BlockSize + 6)) {
2426 if (static_cast<uint32_t>((m[3 + _BlockSize] << 16)
2427 | (m[3 + _BlockSize + 1] << 8)
2428 | (m[3 + _BlockSize + 2])) == CRC24(_BlockSize + 3, m)) {
2429 _BlockSize += 6;
2430 _SkipBytes = _BlockSize;
2431 break;
2432 }
2433 else
2434 ++m;
2435 }
2436 else {
2437 _NeedBytes = _BlockSize + 6; // never 0, also for a zero length field
2438 break;
2439 }
2440 }
2441 else
2442 ++m;
2443 }
2444 if (e - m < 3)
2445 _NeedBytes = 3;
2446
2447 /* copy buffer to front */
2448 i = m - _Message;
2449 if (i && m < e)
2450 memmove(_Message, m, static_cast<size_t>(_MessageSize - i));
2451 _MessageSize -= i;
2452
2453 return !_NeedBytes ? ((_Message[3] << 4) | (_Message[4] >> 4)) : 0;
2454}
2455
2456// Time of Corrections
2457//////////////////////////////////////////////////////////////////////////////
2458int RTCM3Decoder::corrGPSEpochTime() const {
2459 return
2460 _coDecoders.size() > 0 ?
2461 _coDecoders.begin().value()->corrGPSEpochTime() : -1;
2462}
2463
2464// Satellite numbers on the wire can exceed BNC's supported range (e.g. 6-bit
2465// IDs up to 63, while t_prn supports G01-G32). They are passed on unchanged,
2466// but t_prn::toInt() maps them to the unused index 0, so they are not usable
2467// for per-satellite processing - report that once per satellite.
2468////////////////////////////////////////////////////////////////////////////
2469void RTCM3Decoder::checkPrnRange(const t_prn& prn) {
2470 if (prn.toInt() != 0) {
2471 return;
2472 }
2473 QString prnStr = QString::fromStdString(prn.toString());
2474 if (!_prnOutOfRangeLogged.contains(prnStr)) {
2475 _prnOutOfRangeLogged.insert(prnStr);
2476 emit newMessage(QString("%1: satellite %2 outside the range supported by BNC - not usable for processing")
2477 .arg(_staID).arg(prnStr).toLatin1(), true);
2478 }
2479}
Note: See TracBrowser for help on using the repository browser.