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

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

minor changes

File size: 75.6 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
[10619]427/** MSM signal types for NavIC */
[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},
[10619]436 {NavIC_WAVELENGTH_S, "9A"},
[8783]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},
[10619]450 {NavIC_WAVELENGTH_L5, "5A"},
[8783]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////////////////////////////////////////////////////////////////////////////
[10619]1469bool RTCM3Decoder::DecodeNavICEphemeris(unsigned char* data, int size) {
[8783]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;
[10632]1607 eph._health = 0;
[6812]1608 uint64_t numbits = 0, bitfield = 0;
1609
1610 data += 3; /* header */
1611 size -= 6; /* header + crc */
1612 SKIPBITS(12)
1613
1614 eph._receptDateTime = currentDateAndTimeGPS();
[9212]1615 eph._receptStaID = _staID;
[6812]1616
1617 GETBITS(i, 6)
[10554]1618 if (i < 0 || i > 38 ) {
[10549]1619#ifdef BNC_DEBUG_BCE
[10544]1620 emit(newMessage(QString("%1: Block %2 (S) PRN# is out of range: %3!")
1621 .arg(_staID)
1622 .arg(1043,4)
1623 .arg(i).toLatin1(), true));
1624#endif
1625 return false;
1626 }
[10554]1627 eph._prn.set('S', 20 + i);
[6812]1628 GETBITS(eph._IODN, 8)
1629 GETBITS(i, 13)
1630 i <<= 4;
[10544]1631 if (i < 0 || i > 86384) {
[10549]1632#ifdef BNC_DEBUG_BCE
[10544]1633 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1634 .arg(_staID)
1635 .arg(1043,4)
1636 .arg(eph._prn.toString().c_str())
1637 .arg(i).toLatin1(), true));
1638#endif
1639 return false;
1640 }
[8158]1641 eph._TOC.setTOD(i * 1000);
[6812]1642 GETBITS(i, 4)
[10632]1643 int health = 0;
1644 if (i == 15) {
1645 health |= (1 << 5);
1646 // in this case it is recommended
1647 // to set the bits 0,1,2,3 to 1 (MT17health = 15)
1648 health |= (1 << 0);
1649 health |= (1 << 1);
1650 health |= (1 << 2);
1651 health |= (1 << 3);
1652 eph._health = double(health);
1653 }
[10587]1654 eph._ura = accuracyFromIndex(i, eph.system());
[6812]1655 GETFLOATSIGN(eph._x_pos, 30, 0.08)
1656 GETFLOATSIGN(eph._y_pos, 30, 0.08)
1657 GETFLOATSIGN(eph._z_pos, 25, 0.4)
[9201]1658 ColumnVector pos(3);
1659 pos(1) = eph._x_pos; pos(2) = eph._y_pos; pos(3) = eph._z_pos;
1660 if (pos.NormFrobenius() < 1.0) {
[10549]1661#ifdef BNC_DEBUG_BCE
[9201]1662 emit(newMessage(QString("%1: Block %2 (%3): zero position!")
1663 .arg(_staID).arg(1043,4).arg(eph._prn.toString().c_str()).toLatin1(), true));
[9210]1664#endif
[9201]1665 return false;
1666 }
[10587]1667 GETFLOATSIGN(eph._x_vel, 17, 0.000625)
1668 GETFLOATSIGN(eph._y_vel, 17, 0.000625)
1669 GETFLOATSIGN(eph._z_vel, 18, 0.004)
1670 GETFLOATSIGN(eph._x_acc, 10, 0.0000125)
1671 GETFLOATSIGN(eph._y_acc, 10, 0.0000125)
1672 GETFLOATSIGN(eph._z_acc, 10, 0.0000625)
[8158]1673 GETFLOATSIGN(eph._agf0, 12, 1.0 / (1 << 30) / (1 << 1))
1674 GETFLOATSIGN(eph._agf1, 8, 1.0 / (1 << 30) / (1 << 10))
[6812]1675
[8456]1676 eph._TOT = 0.9999E9;
[10632]1677
[10587]1678 eph._type = t_eph::SBASL1;
[10599]1679 eph._prn.setFlag(eph._type);
[6812]1680
1681 emit newSBASEph(eph);
1682 decoded = true;
1683 }
1684 return decoded;
1685}
1686
1687//
1688////////////////////////////////////////////////////////////////////////////
[8158]1689bool RTCM3Decoder::DecodeGalileoEphemeris(unsigned char* data, int size) {
[6812]1690 bool decoded = false;
1691 uint64_t numbits = 0, bitfield = 0;
[10544]1692 int i, week, mnum;
[6812]1693
1694 data += 3; /* header */
1695 size -= 6; /* header + crc */
1696 GETBITS(i, 12)
1697
[10599]1698 if ((i == 1046 && size == 61) ||
1699 (i == 1045 && size == 60)) {
[6812]1700 t_ephGal eph;
1701 eph._receptDateTime = currentDateAndTimeGPS();
[9212]1702 eph._receptStaID = _staID;
[6812]1703
1704 eph._inav = (i == 1046);
1705 eph._fnav = (i == 1045);
[10544]1706 mnum = i;
[6812]1707 GETBITS(i, 6)
[10544]1708 if (i < 1 || i > 36 ) { // max. constellation within I/NAV / F/NAV frames is 36
[10549]1709#ifdef BNC_DEBUG_BCE
[10544]1710 emit(newMessage(QString("%1: Block %2 (E) PRN# is out of range: %3!")
1711 .arg(_staID)
1712 .arg(mnum,4)
1713 .arg(i).toLatin1(), true));
1714#endif
1715 return false;
1716 }
[10599]1717 eph._prn.set('E', i, eph._inav ? t_eph::INAV : t_eph::FNAV);
[6812]1718
[10544]1719 GETBITS(week, 12) //FIXME: roll-over after week 4095!!
1720 if (week < 0 || week > 4095) {
[10549]1721#ifdef BNC_DEBUG_BCE
[10544]1722 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1723 .arg(_staID)
1724 .arg(mnum,4)
1725 .arg(eph._prn.toString().c_str())
1726 .arg(week).toLatin1(), true));
1727#endif
1728 return false;
1729 }
1730 eph._TOEweek = week;
[6812]1731 GETBITS(eph._IODnav, 10)
1732 GETBITS(i, 8)
[10587]1733 eph._SISA = accuracyFromIndex(i, eph.system());
[6812]1734 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1735 GETBITSFACTOR(i, 14, 60)
[10544]1736 if (i < 0 || i > 604740) {
[10549]1737#ifdef BNC_DEBUG_BCE
[10544]1738 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1739 .arg(_staID)
1740 .arg(mnum,4)
1741 .arg(eph._prn.toString().c_str())
1742 .arg(i).toLatin1(), true));
1743#endif
1744 return false;
1745 }
1746 eph._TOC.set(1024 + eph._TOEweek, i);// Period #2 = + 1 x 1024 (has to be determined)
[8783]1747 GETFLOATSIGN(eph._clock_driftrate, 6, 1.0 / (double )(1 << 30) / (double )(1 << 29))
1748 GETFLOATSIGN(eph._clock_drift, 21, 1.0 / (double )(1 << 30) / (double )(1 << 16))
1749 GETFLOATSIGN(eph._clock_bias, 31, 1.0 / (double )(1 << 30) / (double )(1 << 4))
1750 GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
1751 GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
1752 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1753 GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
1754 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1755 GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
1756 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
[6812]1757 GETBITSFACTOR(eph._TOEsec, 14, 60)
[10544]1758 if (i < 0 || i > 604740) {
[10549]1759#ifdef BNC_DEBUG_BCE
[10544]1760 emit(newMessage(QString("%1: Block %2 (%3) TOE 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 }
[6812]1768 /* FIXME: overwrite value, copied from old code */
[10587]1769 //eph._TOEsec = eph._TOC.gpssec();
[8783]1770 GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
1771 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1772 GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
1773 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1774 GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
1775 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
[6812]1776 GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
[8981]1777 GETFLOATSIGN(eph._BGD_1_5A, 10, 1.0 / (double )(1 << 30) / (double )(1 << 2))
[8158]1778 if (eph._inav) {
[10599]1779 eph._type = t_eph::INAV;
[7006]1780 /* set unused F/NAV values */
[10587]1781 eph._E5a_HS = 0.0;
1782 eph._E5a_DataInvalid = false;
[6812]1783
[8783]1784 GETFLOATSIGN(eph._BGD_1_5B, 10, 1.0 / (double )(1 << 30) / (double )(1 << 2))
[10587]1785 GETBITS(eph._E5b_HS, 2)
1786 GETBITS(eph._E5b_DataInvalid, 1)
1787 GETBITS(eph._E1B_HS, 2)
1788 GETBITS(eph._E1B_DataInvalid, 1)
1789 if (eph._E5b_HS != eph._E1B_HS) {
[10549]1790#ifdef BNC_DEBUG_BCE
[9201]1791 emit(newMessage(QString("%1: Block %2 (%3) SHS E5b %4 E1B %5: inconsistent health!")
1792 .arg(_staID).arg(1046,4).arg(eph._prn.toString().c_str())
[10587]1793 .arg(eph._E5b_HS).arg(eph._E1B_HS).toLatin1(), true));
[9210]1794#endif
[9192]1795 return false;
1796 }
1797 if ((eph._BGD_1_5A == 0.0 && fabs(eph._BGD_1_5B) > 1e-9) ||
1798 (eph._BGD_1_5B == 0.0 && fabs(eph._BGD_1_5A) > 1e-9)) {
[10549]1799#ifdef BNC_DEBUG_BCE
[10587]1800 emit(newMessage(QString("%1: Block %2 (%3) BGD_1_5a = %4 BGD_1_5b = %5: inconsistent BGD!")
[9201]1801 .arg(_staID).arg(1046,4).arg(eph._prn.toString().c_str())
1802 .arg(eph._BGD_1_5A,10,'E',3).arg(eph._BGD_1_5B,10,'E',3).toLatin1(), true));
[9210]1803#endif
[9192]1804 return false;
1805 }
[6812]1806 }
[8158]1807 else {
[10599]1808 eph._type = t_eph::FNAV;
[7006]1809 /* set unused I/NAV values */
[6812]1810 eph._BGD_1_5B = 0.0;
[10587]1811 eph._E5b_HS = 0.0;
1812 eph._E1B_HS = 0.0;
1813 eph._E1B_DataInvalid = false;
1814 eph._E5b_DataInvalid = false;
[6812]1815
[10587]1816 GETBITS(eph._E5a_HS, 2)
1817 GETBITS(eph._E5a_DataInvalid, 1)
[6812]1818 }
1819 eph._TOT = 0.9999e9;
1820
[9201]1821 if (eph._sqrt_A < 1000.0) {
[10549]1822#ifdef BNC_DEBUG_BCE
[9201]1823 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1824 .arg(_staID).arg(eph._inav? 1046 : 1045,4).arg(eph._prn.toString().c_str())
1825 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
[9210]1826#endif
[9201]1827 return false;
1828 }
1829
[6812]1830 emit newGalileoEph(eph);
1831 decoded = true;
1832 }
1833 return decoded;
1834}
1835
1836//
1837////////////////////////////////////////////////////////////////////////////
[8158]1838bool RTCM3Decoder::DecodeBDSEphemeris(unsigned char* data, int size) {
[6812]1839 bool decoded = false;
[9765]1840 const double iMaxGEO = 10.0 / 180.0 * M_PI;
[6812]1841
[8158]1842 if (size == 70) {
[6812]1843 t_ephBDS eph;
[10544]1844 int i, week;
[6812]1845 uint64_t numbits = 0, bitfield = 0;
1846
1847 data += 3; /* header */
1848 size -= 6; /* header + crc */
1849 SKIPBITS(12)
1850
1851 eph._receptDateTime = currentDateAndTimeGPS();
[9212]1852 eph._receptStaID = _staID;
[6812]1853
1854 GETBITS(i, 6)
[10544]1855 if (i < 1 || i > 63 ) {
[10549]1856#ifdef BNC_DEBUG_BCE
[10544]1857 emit(newMessage(QString("%1: Block %2 (C) PRN# is out of range: %3!")
1858 .arg(_staID)
1859 .arg(1042,4)
1860 .arg(i).toLatin1(), true));
1861#endif
1862 return false;
1863 }
[6812]1864 eph._prn.set('C', i);
1865
[10544]1866 GETBITS(week, 13)
1867 if (week < 0 || week > 8191) {
[10549]1868#ifdef BNC_DEBUG_BCE
[10544]1869 emit(newMessage(QString("%1: Block %2 (%3) WEEK # is out of range: %4!")
1870 .arg(_staID)
1871 .arg(1042,4)
1872 .arg(eph._prn.toString().c_str())
1873 .arg(week).toLatin1(), true));
1874#endif
1875 return false;
1876 }
1877 eph._BDTweek = week;
[6812]1878 GETBITS(i, 4)
[10587]1879 eph._ura = accuracyFromIndex(i, eph.system());
[6812]1880 GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
1881 GETBITS(eph._AODE, 5)
1882 GETBITS(i, 17)
1883 i <<= 3;
[10544]1884 if (i < 0 || i > 604792) {
[10549]1885#ifdef BNC_DEBUG_BCE
[10544]1886 emit(newMessage(QString("%1: Block %2 (%3) TOC is out of range: %4!")
1887 .arg(_staID)
1888 .arg(1042,4)
1889 .arg(eph._prn.toString().c_str())
1890 .arg(i).toLatin1(), true));
1891#endif
1892 return false;
1893 }
[9785]1894 eph._TOC.setBDS(eph._BDTweek, i);
[8783]1895 GETFLOATSIGN(eph._clock_driftrate, 11, 1.0 / (double )(1 << 30) / (double )(1 << 30) / (double )(1 << 6))
1896 GETFLOATSIGN(eph._clock_drift, 22, 1.0 / (double )(1 << 30) / (double )(1 << 20))
1897 GETFLOATSIGN(eph._clock_bias, 24, 1.0 / (double )(1 << 30) / (double )(1 << 3))
[6812]1898 GETBITS(eph._AODC, 5)
[8783]1899 GETFLOATSIGN(eph._Crs, 18, 1.0 / (double )(1 << 6))
[6812]1900 GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
[8783]1901 GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1902 GETFLOATSIGN(eph._Cuc, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1903 GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
1904 GETFLOATSIGN(eph._Cus, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1905 GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
[9201]1906 if (eph._sqrt_A < 1000.0) {
[10549]1907#ifdef BNC_DEBUG_BCE
[9201]1908 emit(newMessage(QString("%1: Block %2 (%3) SQRT_A %4 m!")
1909 .arg(_staID).arg(1042,4).arg(eph._prn.toString().c_str())
1910 .arg(eph._sqrt_A,10,'F',3).toLatin1(), true));
[9210]1911#endif
[9201]1912 return false;
1913 }
[6812]1914 GETBITS(i, 17)
1915 i <<= 3;
[10544]1916 if (i < 0 || i > 604792) {
[10549]1917#ifdef BNC_DEBUG_BCE
[10544]1918 emit(newMessage(QString("%1: Block %2 (%3) TOE is out of range: %4!")
1919 .arg(_staID)
1920 .arg(1042,4)
1921 .arg(eph._prn.toString().c_str())
1922 .arg(i).toLatin1(), true));
1923#endif
1924 return false;
1925 }
[6812]1926 eph._TOEsec = i;
[9785]1927 eph._TOE.setBDS(eph._BDTweek, i);
[8783]1928 GETFLOATSIGN(eph._Cic, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1929 GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1930 GETFLOATSIGN(eph._Cis, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
1931 GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
1932 GETFLOATSIGN(eph._Crc, 18, 1.0 / (double )(1 << 6))
1933 GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
[6812]1934 GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
[8783]1935 GETFLOATSIGN(eph._TGD1, 10, 0.0000000001)
1936 GETFLOATSIGN(eph._TGD2, 10, 0.0000000001)
[6812]1937 GETBITS(eph._SatH1, 1)
1938
[8456]1939 eph._TOT = 0.9999E9;
[9765]1940 if (eph._i0 > iMaxGEO) {
[10587]1941 eph._type = t_eph::D1;
[9765]1942 }
1943 else {
[10587]1944 eph._type = t_eph::D2;
[9765]1945 }
[10599]1946 eph._prn.setFlag(eph._type);
[9765]1947
[6812]1948 emit newBDSEph(eph);
1949 decoded = true;
1950 }
1951 return decoded;
1952}
1953
[8197]1954//
1955////////////////////////////////////////////////////////////////////////////
1956bool RTCM3Decoder::DecodeAntennaReceiver(unsigned char* data, int size) {
[8234]1957 char *antenna;
1958 char *antserialnum;
1959 char *receiver;
1960 char *recfirmware;
1961 char *recserialnum;
[8197]1962 int type;
[8234]1963 int antsernum = -1;
[8197]1964 int antnum = -1;
1965 int recnum = -1;
[8234]1966 int recsernum = -1;
1967 int recfirnum = -1;
[8197]1968 uint64_t numbits = 0, bitfield = 0;
1969
1970 data += 3; /* header*/
1971 size -= 6; /* header + crc */
1972
[8198]1973 GETBITS(type, 12)
[8234]1974 SKIPBITS(12) /* reference station ID */
[8197]1975 GETSTRING(antnum, antenna)
[8234]1976 if ((antnum > -1 && antnum < 265) &&
1977 (_antType.empty() || strncmp(_antType.back().descriptor, antenna, recnum) != 0)) {
1978 _antType.push_back(t_antInfo());
1979 memcpy(_antType.back().descriptor, antenna, antnum);
1980 _antType.back().descriptor[antnum] = 0;
1981 }
1982 SKIPBITS(8) /* antenna setup ID */
1983 if (type == 1008 || type == 1033 ) {
1984 GETSTRING(antsernum, antserialnum)
1985 if ((antsernum > -1 && antsernum < 265)) {
1986 memcpy(_antType.back().serialnumber, antserialnum, antsernum);
1987 _antType.back().serialnumber[antsernum] = 0;
[8197]1988 }
1989 }
[8234]1990
[8197]1991 if (type == 1033) {
1992 GETSTRING(recnum, receiver)
[8234]1993 GETSTRING(recfirnum, recfirmware)
1994 GETSTRING(recsernum, recserialnum)
1995 if ((recnum > -1 && recnum < 265) &&
1996 (_recType.empty() || strncmp(_recType.back().descriptor, receiver, recnum) != 0)) {
1997 _recType.push_back(t_recInfo());
1998 memcpy(_recType.back().descriptor, receiver, recnum);
1999 _recType.back().descriptor[recnum] = 0;
2000 if (recfirnum > -1 && recfirnum < 265) {
2001 memcpy(_recType.back().firmware, recfirmware, recfirnum);
2002 _recType.back().firmware[recfirnum] = 0;
[8197]2003 }
[8234]2004 if (recsernum > -1 && recsernum < 265) {
2005 memcpy(_recType.back().serialnumber, recserialnum, recsernum);
2006 _recType.back().serialnumber[recsernum] = 0;
2007 }
[8197]2008 }
2009 }
2010 return true;
[6812]2011}
2012
2013//
2014////////////////////////////////////////////////////////////////////////////
[8158]2015bool RTCM3Decoder::DecodeAntennaPosition(unsigned char* data, int size) {
[6812]2016 int type;
2017 uint64_t numbits = 0, bitfield = 0;
2018 double x, y, z;
2019
2020 data += 3; /* header */
2021 size -= 6; /* header + crc */
2022
2023 GETBITS(type, 12)
[8234]2024 _antList.push_back(t_antRefPoint());
2025 _antList.back().type = t_antRefPoint::ARP;
[6812]2026 SKIPBITS(22)
2027 GETBITSSIGN(x, 38)
2028 _antList.back().xx = x * 1e-4;
2029 SKIPBITS(2)
2030 GETBITSSIGN(y, 38)
2031 _antList.back().yy = y * 1e-4;
2032 SKIPBITS(2)
2033 GETBITSSIGN(z, 38)
2034 _antList.back().zz = z * 1e-4;
[10534]2035 if (type == 1006) {
[6812]2036 double h;
2037 GETBITS(h, 16)
2038 _antList.back().height = h * 1e-4;
2039 _antList.back().height_f = true;
2040 }
[8158]2041 _antList.back().message = type;
[6812]2042
2043 return true;
2044}
2045
[7753]2046//
[6812]2047////////////////////////////////////////////////////////////////////////////
[10534]2048bool RTCM3Decoder::DecodeServiceCRS(unsigned char* data, int size) {
2049 t_serviceCrs serviceCrs;
2050 int servicecrsnum = -1;
2051
2052 uint64_t numbits = 0, bitfield = 0;
2053
2054 data += 3; // header
2055 size -= 6; // header + crc
2056
2057 SKIPBITS(12) // Message Number
2058
2059 GETBITS(servicecrsnum, 5)
2060 if (servicecrsnum > -1 && servicecrsnum <= 31) {
2061 for(int i = 0; i < servicecrsnum; i++) {
2062 GETBITS(serviceCrs._name[i], 8);
2063 }
2064 serviceCrs._name[servicecrsnum] = 0;
2065 }
2066 if (_serviceCrs.empty() ||
2067 (strncmp(_serviceCrs.back()._name, serviceCrs._name, servicecrsnum) != 0)) {
2068 _serviceCrs.push_back(serviceCrs);
2069 GETFLOAT(_serviceCrs.back()._CE, 16, 1/100.0)
2070 _serviceCrs.back().setCoordinateEpochFromCE();
[10539]2071 //_serviceCrs.back().print();
[10534]2072 }
2073 return true;
2074
2075}
2076
2077//
2078////////////////////////////////////////////////////////////////////////////
2079bool RTCM3Decoder::DecodeRTCMCRS(unsigned char* data, int size) {
2080
2081 t_rtcmCrs rtcmCrs;
2082 int rtcmcrsnum = -1;
2083
2084 uint64_t numbits = 0, bitfield = 0;
2085
2086 data += 3; // header
2087 size -= 6; // header + crc
2088
2089 SKIPBITS(12) // Message Number
2090 GETBITS(rtcmcrsnum, 5)
2091 if (rtcmcrsnum > -1 && rtcmcrsnum <= 31) {
2092 for(int i = 0; i < rtcmcrsnum; i++) {
2093 GETBITS(rtcmCrs._name[i], 8);
2094 }
2095 rtcmCrs._name[rtcmcrsnum] = 0;
2096 }
2097 if (_rtcmCrs.empty() ||
2098 (strncmp(_rtcmCrs.back()._name, rtcmCrs._name, rtcmcrsnum) != 0)) {
2099 _rtcmCrs.push_back(rtcmCrs);
2100
2101 GETBITS(_rtcmCrs.back()._anchor, 1)
2102 GETBITS(_rtcmCrs.back()._plateNumber, 5)
2103
2104 int dblinksnum = 0;
2105 GETBITS(dblinksnum, 3)
2106 for (int i = 0; i < dblinksnum; i++) {
2107 int dblinknum = -1;
2108 char dblinkname[31];
2109 GETBITS(dblinknum, 5)
2110 if (dblinknum > -1 && dblinknum <= 31) {
2111 for(int i = 0; i < dblinknum; i++) {
2112 GETBITS(dblinkname[i], 8);
2113 }
2114 dblinkname[dblinknum] = 0;
2115 _rtcmCrs.back()._databaseLinks.append(QString("%1").arg(dblinkname));
2116 }
2117 }
[10539]2118 //_rtcmCrs.back().print();
[10534]2119 }
2120
2121 return true;
2122}
2123
2124
2125////////////////////////////////////////////////////////////////////////////
2126bool RTCM3Decoder::DecodeHelmertTrafoParameters(unsigned char* data, int size) {
2127
2128 t_helmertPar helmertPar;
2129 int sourcenum = -1;
2130 int targetnum = -1;
2131
2132 uint64_t numbits = 0, bitfield = 0;
2133 data += 3; // header
2134 size -= 6; // header + crc
2135
2136 SKIPBITS(12) // Message Number
2137 GETBITS(sourcenum, 5)
2138 if (sourcenum > -1 && sourcenum <= 31) {
2139 for(int i = 0; i < sourcenum; i++) {
2140 GETBITS(helmertPar._sourceName[i], 8);
2141 }
2142 helmertPar._sourceName[sourcenum] = 0;
2143 }
2144 GETBITS(targetnum, 5)
2145 if (targetnum > -1 && targetnum <= 31) {
2146 for(int i = 0; i < targetnum; i++) {
2147 GETBITS(helmertPar._targetName[i], 8);
2148 }
2149 helmertPar._targetName[targetnum] = 0;
2150 }
2151 GETBITS(helmertPar._sysIdentNum, 8)
2152 GETBITS(helmertPar._utilTrafoMessageIndicator, 10)
[10545]2153 GETBITS(helmertPar._mjd, 16)
2154 helmertPar._mjd += 44244;
[10534]2155
2156 // delete old parameter entries if available
2157 if (!_helmertPar.empty()) {
2158 QList<t_helmertPar>::iterator it = _helmertPar.begin();
2159 while (it != _helmertPar.end()) {
2160 (helmertPar == *it) ? it = _helmertPar.erase(it) : ++it;
2161 }
2162 }
2163 _helmertPar.push_back(helmertPar);
2164
[10545]2165 GETFLOATSIGN(_helmertPar.back()._dx, 23, 1/1000.0)
2166 GETFLOATSIGN(_helmertPar.back()._dy, 23, 1/1000.0)
2167 GETFLOATSIGN(_helmertPar.back()._dz, 23, 1/1000.0)
[10534]2168
[10545]2169 GETFLOATSIGN(_helmertPar.back()._ox, 32, 1/50000.0)
2170 GETFLOATSIGN(_helmertPar.back()._oy, 32, 1/50000.0)
2171 GETFLOATSIGN(_helmertPar.back()._oz, 32, 1/50000.0)
2172
2173 GETFLOATSIGN(_helmertPar.back()._sc, 25, 1/100000.0)
2174
2175 GETFLOATSIGN(_helmertPar.back()._dxr, 17, 1/50000.0)
2176 GETFLOATSIGN(_helmertPar.back()._dyr, 17, 1/50000.0)
2177 GETFLOATSIGN(_helmertPar.back()._dzr, 17, 1/50000.0)
2178
2179 GETFLOATSIGN(_helmertPar.back()._oxr, 17, 1/2500000.0)
2180 GETFLOATSIGN(_helmertPar.back()._oyr, 17, 1/2500000.0)
2181 GETFLOATSIGN(_helmertPar.back()._ozr, 17, 1/2500000.0)
2182
2183 GETFLOATSIGN(_helmertPar.back()._scr, 14, 1/5000000.0)
2184
[10539]2185 //_helmertPar.back().print();
[10534]2186
2187 return true;
2188}
2189
2190
2191//
2192////////////////////////////////////////////////////////////////////////////
[8158]2193t_irc RTCM3Decoder::Decode(char* buffer, int bufLen, vector<string>& errmsg) {
[6812]2194 bool decoded = false;
2195
2196 errmsg.clear();
2197
[8158]2198 while (bufLen && _MessageSize < sizeof(_Message)) {
[6812]2199 int l = sizeof(_Message) - _MessageSize;
[8158]2200 if (l > bufLen)
[6812]2201 l = bufLen;
[8158]2202 memcpy(_Message + _MessageSize, buffer, l);
[6812]2203 _MessageSize += l;
2204 bufLen -= l;
2205 buffer += l;
2206 int id;
[8158]2207 while ((id = GetMessage())) {
[6812]2208 /* reset station ID for file loading as it can change */
[8158]2209 if (_rawFile)
[6812]2210 _staID = _rawFile->staID();
2211 /* store the id into the list of loaded blocks */
2212 _typeList.push_back(id);
2213
[6856]2214 /* SSR I+II data handled in another function, already pass the
[6812]2215 * extracted data block. That does no harm, as it anyway skip everything
2216 * else. */
[8971]2217 if ((id >= 1057 && id <= 1068) ||
[9212]2218 (id >= 1240 && id <= 1270) ||
2219 (id == 4076)) {
[9048]2220 if (!_coDecoders.contains(_staID.toLatin1())) {
2221 _coDecoders[_staID.toLatin1()] = new RTCM3coDecoder(_staID);
[9306]2222 if (id == 4076) {
2223 _coDecoders[_staID.toLatin1()]->initSsrFormatType(RTCM3coDecoder::IGSssr);
2224 }
2225 else {
2226 _coDecoders[_staID.toLatin1()]->initSsrFormatType(RTCM3coDecoder::RTCMssr);
2227 }
[9048]2228 }
2229 RTCM3coDecoder* coDecoder = _coDecoders[_staID.toLatin1()];
[9212]2230 if (coDecoder->Decode(reinterpret_cast<char *>(_Message), _BlockSize, errmsg) == success) {
[6812]2231 decoded = true;
2232 }
2233 }
[9285]2234 else if (id >= 1070 && id <= 1237) { /* MSM */
[8158]2235 if (DecodeRTCM3MSM(_Message, _BlockSize))
[6812]2236 decoded = true;
2237 }
[8158]2238 else {
2239 switch (id) {
2240 case 1001:
2241 case 1003:
[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 1002:
2248 case 1004:
2249 if (DecodeRTCM3GPS(_Message, _BlockSize))
2250 decoded = true;
2251 break;
2252 case 1009:
2253 case 1011:
[10236]2254#ifdef BNC_DEBUG_OBS
[9210]2255 emit(newMessage(QString("%1: Block %2 contain partial data! Ignored!")
2256 .arg(_staID).arg(id).toLatin1(), true));
[10236]2257#endif
[8158]2258 break; /* no use decoding partial data ATM, remove break when data can be used */
2259 case 1010:
2260 case 1012:
2261 if (DecodeRTCM3GLONASS(_Message, _BlockSize))
2262 decoded = true;
2263 break;
2264 case 1019:
2265 if (DecodeGPSEphemeris(_Message, _BlockSize))
2266 decoded = true;
2267 break;
2268 case 1020:
2269 if (DecodeGLONASSEphemeris(_Message, _BlockSize))
2270 decoded = true;
2271 break;
2272 case 1043:
2273 if (DecodeSBASEphemeris(_Message, _BlockSize))
2274 decoded = true;
2275 break;
2276 case 1044:
2277 if (DecodeQZSSEphemeris(_Message, _BlockSize))
2278 decoded = true;
2279 break;
[9002]2280 case 1041:
[10619]2281 if (DecodeNavICEphemeris(_Message, _BlockSize))
[8783]2282 decoded = true;
2283 break;
[8158]2284 case 1045:
2285 case 1046:
2286 if (DecodeGalileoEphemeris(_Message, _BlockSize))
2287 decoded = true;
2288 break;
[9000]2289 case 1042:
[8158]2290 if (DecodeBDSEphemeris(_Message, _BlockSize))
2291 decoded = true;
2292 break;
2293 case 1007:
2294 case 1008:
2295 case 1033:
[8197]2296 DecodeAntennaReceiver(_Message, _BlockSize);
[8158]2297 break;
2298 case 1005:
2299 case 1006:
2300 DecodeAntennaPosition(_Message, _BlockSize);
2301 break;
[10534]2302 case 1300:
2303 DecodeServiceCRS(_Message, _BlockSize);
2304 break;
2305 case 1301:
2306 DecodeHelmertTrafoParameters(_Message, _BlockSize);
2307 break;
2308 case 1302:
2309 case 35:
2310 DecodeRTCMCRS(_Message, _BlockSize);
2311 break;
[296]2312 }
2313 }
2314 }
[6812]2315 }
[10534]2316 /*
2317 for (int ii = 0; ii < _helmertParList.size(); ii++) {
2318 _helmertParList[ii].print();
2319 }*/
[6812]2320 return decoded ? success : failure;
[8158]2321}
[6812]2322
[7753]2323//
[6812]2324////////////////////////////////////////////////////////////////////////////
[8158]2325uint32_t RTCM3Decoder::CRC24(long size, const unsigned char *buf) {
[6812]2326 uint32_t crc = 0;
[9025]2327 int ii;
[8158]2328 while (size--) {
[6812]2329 crc ^= (*buf++) << (16);
[9025]2330 for (ii = 0; ii < 8; ii++) {
[6812]2331 crc <<= 1;
[8158]2332 if (crc & 0x1000000)
[6812]2333 crc ^= 0x01864cfb;
[1021]2334 }
[296]2335 }
[6812]2336 return crc;
2337}
[1021]2338
[7753]2339//
[6812]2340////////////////////////////////////////////////////////////////////////////
[8158]2341int RTCM3Decoder::GetMessage(void) {
[6812]2342 unsigned char *m, *e;
2343 int i;
2344
[8158]2345 m = _Message + _SkipBytes;
2346 e = _Message + _MessageSize;
[6812]2347 _NeedBytes = _SkipBytes = 0;
[8158]2348 while (e - m >= 3) {
2349 if (m[0] == 0xD3) {
2350 _BlockSize = ((m[1] & 3) << 8) | m[2];
2351 if (e - m >= static_cast<int>(_BlockSize + 6)) {
2352 if (static_cast<uint32_t>((m[3 + _BlockSize] << 16)
2353 | (m[3 + _BlockSize + 1] << 8)
2354 | (m[3 + _BlockSize + 2])) == CRC24(_BlockSize + 3, m)) {
2355 _BlockSize += 6;
[6812]2356 _SkipBytes = _BlockSize;
2357 break;
2358 }
2359 else
2360 ++m;
2361 }
[8158]2362 else {
[6812]2363 _NeedBytes = _BlockSize;
2364 break;
2365 }
2366 }
2367 else
2368 ++m;
[658]2369 }
[8158]2370 if (e - m < 3)
[6812]2371 _NeedBytes = 3;
2372
2373 /* copy buffer to front */
2374 i = m - _Message;
[8158]2375 if (i && m < e)
2376 memmove(_Message, m, static_cast<size_t>(_MessageSize - i));
[6812]2377 _MessageSize -= i;
2378
[8158]2379 return !_NeedBytes ? ((_Message[3] << 4) | (_Message[4] >> 4)) : 0;
[296]2380}
[1807]2381
[3001]2382// Time of Corrections
2383//////////////////////////////////////////////////////////////////////////////
2384int RTCM3Decoder::corrGPSEpochTime() const {
[8158]2385 return
2386 _coDecoders.size() > 0 ?
2387 _coDecoders.begin().value()->corrGPSEpochTime() : -1;
[3001]2388}
[10544]2389
2390
2391
2392
Note: See TracBrowser for help on using the repository browser.