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

Last change on this file since 10899 was 10899, checked in by stuerze, 12 days ago

bugfix in NavIC broadcast epehemeris encoding/decoding

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