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

Last change on this file since 11049 was 11049, checked in by stuerze, 7 days ago

minor changes

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