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

Last change on this file since 10603 was 10599, checked in by stuerze, 2 weeks ago

ADDED: consideration of NAV type in all applications

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