gnss-js 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -215,10 +215,13 @@ __export(src_exports, {
215
215
  parseIonex: () => parseIonex,
216
216
  parseNavFile: () => parseNavFile,
217
217
  parseNmeaFile: () => parseNmeaFile,
218
+ parseNovatelRange: () => parseNovatelRange,
218
219
  parseRinexStream: () => parseRinexStream,
220
+ parseSbfMeas: () => parseSbfMeas,
219
221
  parseSinexBiasDcb: () => parseSinexBiasDcb,
220
222
  parseSourcetable: () => parseSourcetable,
221
223
  parseSp3: () => parseSp3,
224
+ parseUbxRawx: () => parseUbxRawx,
222
225
  phiAltBOC: () => phiAltBOC,
223
226
  phiBOCc: () => phiBOCc,
224
227
  phiBOCs: () => phiBOCs,
@@ -4591,6 +4594,1082 @@ function updateStreamStats(stats, frames, rawBytes) {
4591
4594
  }
4592
4595
  }
4593
4596
 
4597
+ // src/ubx/index.ts
4598
+ var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
4599
+ var MS_PER_WEEK2 = 7 * 864e5;
4600
+ var SIGNALS = {
4601
+ 0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
4602
+ // GPS L1C/A, L2CL, L2CM
4603
+ 1: { 0: ["S", "1C"] },
4604
+ // SBAS L1C/A
4605
+ 2: { 0: ["E", "1X"], 1: ["E", "1X"], 5: ["E", "7X"], 6: ["E", "7X"] },
4606
+ // E1C/B, E5bI/Q
4607
+ 3: { 0: ["C", "2I"], 1: ["C", "2I"], 2: ["C", "7I"], 3: ["C", "7I"] },
4608
+ // B1I D1/D2, B2I D1/D2
4609
+ 5: { 0: ["J", "1C"], 4: ["J", "2X"], 5: ["J", "2X"] },
4610
+ // QZSS L1C/A, L2CM/CL
4611
+ 6: { 0: ["R", "1C"], 2: ["R", "2C"] }
4612
+ // GLONASS L1OF, L2OF
4613
+ };
4614
+ function prnFor(gnssId, svId) {
4615
+ const two2 = (n) => String(n).padStart(2, "0");
4616
+ switch (gnssId) {
4617
+ case 0:
4618
+ return svId >= 1 && svId <= 32 ? `G${two2(svId)}` : null;
4619
+ case 1:
4620
+ return svId >= 120 && svId <= 158 ? `S${two2(svId - 100)}` : null;
4621
+ case 2:
4622
+ return svId >= 1 && svId <= 36 ? `E${two2(svId)}` : null;
4623
+ case 3:
4624
+ return svId >= 1 && svId <= 63 ? `C${two2(svId)}` : null;
4625
+ case 5:
4626
+ return svId >= 1 && svId <= 10 ? `J${two2(svId)}` : null;
4627
+ case 6:
4628
+ return svId >= 1 && svId <= 32 ? `R${two2(svId)}` : null;
4629
+ default:
4630
+ return null;
4631
+ }
4632
+ }
4633
+ function parseUbxRawx(data) {
4634
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
4635
+ const epochs = [];
4636
+ const messageCounts = {};
4637
+ const obsCodes = {};
4638
+ let badChecksums = 0;
4639
+ let i = 0;
4640
+ while (i + 8 <= data.length) {
4641
+ if (data[i] !== 181 || data[i + 1] !== 98) {
4642
+ i++;
4643
+ continue;
4644
+ }
4645
+ const cls = data[i + 2];
4646
+ const id = data[i + 3];
4647
+ const len = data[i + 4] | data[i + 5] << 8;
4648
+ const end = i + 6 + len + 2;
4649
+ if (end > data.length) break;
4650
+ let ckA = 0;
4651
+ let ckB = 0;
4652
+ for (let j = i + 2; j < i + 6 + len; j++) {
4653
+ ckA = ckA + data[j] & 255;
4654
+ ckB = ckB + ckA & 255;
4655
+ }
4656
+ if (ckA !== data[i + 6 + len] || ckB !== data[i + 7 + len]) {
4657
+ badChecksums++;
4658
+ i++;
4659
+ continue;
4660
+ }
4661
+ const key = `${cls.toString(16).padStart(2, "0")}-${id.toString(16).padStart(2, "0")}`;
4662
+ messageCounts[key] = (messageCounts[key] ?? 0) + 1;
4663
+ if (cls === 2 && id === 21 && len >= 16) {
4664
+ const p = i + 6;
4665
+ const rcvTow = view.getFloat64(p, true);
4666
+ const week = view.getUint16(p + 8, true);
4667
+ const leapS = view.getInt8(p + 10);
4668
+ const numMeas = data[p + 11];
4669
+ const recStat = data[p + 12];
4670
+ const leapValid = (recStat & 1) !== 0;
4671
+ const meas = [];
4672
+ for (let k = 0; k < numMeas; k++) {
4673
+ const off = p + 16 + 32 * k;
4674
+ if (off + 32 > p + len) break;
4675
+ const gnssId = data[off + 20];
4676
+ const svId = data[off + 21];
4677
+ const sigId = data[off + 22];
4678
+ const trkStat = data[off + 30];
4679
+ const prn = prnFor(gnssId, svId);
4680
+ const sig = SIGNALS[gnssId]?.[sigId];
4681
+ if (!prn || !sig) continue;
4682
+ const prValid = (trkStat & 1) !== 0;
4683
+ const cpValid = (trkStat & 2) !== 0;
4684
+ const cp = view.getFloat64(off + 8, true);
4685
+ meas.push({
4686
+ prn,
4687
+ code: sig[1],
4688
+ pr: prValid ? view.getFloat64(off, true) : null,
4689
+ cp: cpValid && cp !== 0 ? cp : null,
4690
+ doppler: view.getFloat32(off + 16, true),
4691
+ cn0: data[off + 26],
4692
+ halfCycleAmbiguous: (trkStat & 4) !== 0,
4693
+ lockTimeMs: view.getUint16(off + 24, true)
4694
+ });
4695
+ const sys = sig[0];
4696
+ const codes = obsCodes[sys] ??= [];
4697
+ if (!codes.includes(sig[1])) codes.push(sig[1]);
4698
+ }
4699
+ epochs.push({
4700
+ timeMs: GPS_EPOCH_MS + week * MS_PER_WEEK2 + Math.round(rcvTow * 1e3),
4701
+ leapS: leapValid ? leapS : null,
4702
+ meas
4703
+ });
4704
+ }
4705
+ i = end;
4706
+ }
4707
+ return { epochs, messageCounts, obsCodes, badChecksums };
4708
+ }
4709
+
4710
+ // src/sbf/index.ts
4711
+ var CLIGHT = 299792458;
4712
+ var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
4713
+ var MS_PER_WEEK3 = 7 * 864e5;
4714
+ var CRC_TABLE = (() => {
4715
+ const t = new Uint16Array(256);
4716
+ for (let n = 0; n < 256; n++) {
4717
+ let c = n << 8;
4718
+ for (let k = 0; k < 8; k++)
4719
+ c = c & 32768 ? (c << 1 ^ 4129) & 65535 : c << 1 & 65535;
4720
+ t[n] = c;
4721
+ }
4722
+ return t;
4723
+ })();
4724
+ function crc16(data, start, end) {
4725
+ let crc = 0;
4726
+ for (let i = start; i < end; i++)
4727
+ crc = (crc << 8 ^ CRC_TABLE[(crc >> 8 ^ data[i]) & 255]) & 65535;
4728
+ return crc;
4729
+ }
4730
+ var M3_SYS = ["G", "R", "E", "C", "S", "J", "I"];
4731
+ var M3_PR_BASE = [19e6, 19e6, 22e6, 2e7, 34e6, 34e6, 34e6];
4732
+ var M3_INTERVALS = [
4733
+ 1,
4734
+ 500,
4735
+ 1e3,
4736
+ 2e3,
4737
+ 5e3,
4738
+ 1e4,
4739
+ 15e3,
4740
+ 3e4,
4741
+ 6e4,
4742
+ 12e4,
4743
+ 1,
4744
+ 1,
4745
+ 1,
4746
+ 1,
4747
+ 1,
4748
+ 1
4749
+ ];
4750
+ var M3_LOCK_TIME = [
4751
+ 0,
4752
+ 6e4,
4753
+ 3e4,
4754
+ 15e3,
4755
+ 1e4,
4756
+ 5e3,
4757
+ 2e3,
4758
+ 1e3,
4759
+ 500,
4760
+ 200,
4761
+ 100,
4762
+ 50,
4763
+ 40,
4764
+ 20,
4765
+ 10,
4766
+ 0
4767
+ ];
4768
+ var M3_SIG_DEFAULT = [
4769
+ ["1C", "2L", "5Q", "1W", "2W", "1L"],
4770
+ // GPS
4771
+ ["1C", "2C", "1P", "2P", "3Q"],
4772
+ // GLONASS
4773
+ ["1C", "5Q", "7Q", "6C", "8Q"],
4774
+ // Galileo
4775
+ ["2I", "7I", "6I", "1P", "5P", "7D"],
4776
+ // BeiDou
4777
+ ["1C", "5I"],
4778
+ // SBAS
4779
+ ["1C", "2L", "5Q", "6L", "1L", "1Z", "5P", "1E"],
4780
+ // QZSS
4781
+ ["5A", "1E", "9A"]
4782
+ // NavIC
4783
+ ];
4784
+ var MEAS2_SIG = [
4785
+ ["G", "1C"],
4786
+ ["G", "1W"],
4787
+ ["G", "2W"],
4788
+ ["G", "2L"],
4789
+ ["G", "5Q"],
4790
+ ["G", "1L"],
4791
+ ["J", "1C"],
4792
+ ["J", "2L"],
4793
+ ["R", "1C"],
4794
+ ["R", "1P"],
4795
+ ["R", "2P"],
4796
+ ["R", "2C"],
4797
+ ["R", "3Q"],
4798
+ ["C", "1P"],
4799
+ ["C", "5P"],
4800
+ ["I", "5A"],
4801
+ null,
4802
+ ["E", "1C"],
4803
+ null,
4804
+ ["E", "6C"],
4805
+ ["E", "5Q"],
4806
+ ["E", "7Q"],
4807
+ ["E", "8Q"],
4808
+ null,
4809
+ // L-band
4810
+ ["S", "1C"],
4811
+ ["S", "5I"],
4812
+ ["J", "5Q"],
4813
+ ["J", "6L"],
4814
+ ["C", "2I"],
4815
+ ["C", "7I"],
4816
+ ["C", "6I"],
4817
+ null,
4818
+ ["J", "1L"],
4819
+ ["J", "1Z"],
4820
+ ["C", "7D"],
4821
+ null,
4822
+ ["I", "9A"],
4823
+ null,
4824
+ // NavIC L1 (no obs code assigned)
4825
+ ["J", "1E"],
4826
+ ["J", "5P"]
4827
+ ];
4828
+ var two = (n) => String(n).padStart(2, "0");
4829
+ function m3Prn(navsys, svid) {
4830
+ switch (navsys) {
4831
+ case 0:
4832
+ return svid < 32 ? `G${two(svid + 1)}` : null;
4833
+ case 1:
4834
+ return svid < 27 ? `R${two(svid + 1)}` : null;
4835
+ case 2:
4836
+ return svid < 36 ? `E${two(svid + 1)}` : null;
4837
+ case 3:
4838
+ return svid < 50 ? `C${two(svid + 1)}` : null;
4839
+ case 4:
4840
+ return svid <= 38 ? `S${two(svid + 20)}` : null;
4841
+ case 5:
4842
+ return svid < 10 ? `J${two(svid + 1)}` : null;
4843
+ case 6:
4844
+ return svid < 14 ? `I${two(svid + 1)}` : null;
4845
+ default:
4846
+ return null;
4847
+ }
4848
+ }
4849
+ function svidToPrn(svid) {
4850
+ if (svid >= 1 && svid <= 37) return svid <= 32 ? `G${two(svid)}` : null;
4851
+ if (svid <= 61) return svid - 37 <= 27 ? `R${two(svid - 37)}` : null;
4852
+ if (svid <= 62) return null;
4853
+ if (svid <= 68) return svid - 38 <= 27 ? `R${two(svid - 38)}` : null;
4854
+ if (svid <= 70) return null;
4855
+ if (svid <= 106) return svid - 70 <= 36 ? `E${two(svid - 70)}` : null;
4856
+ if (svid <= 119) return null;
4857
+ if (svid <= 140) return `S${two(svid - 100)}`;
4858
+ if (svid <= 180) return svid - 140 <= 50 ? `C${two(svid - 140)}` : null;
4859
+ if (svid <= 190) return `J${two(svid - 180)}`;
4860
+ if (svid <= 197) return svid - 190 <= 14 ? `I${two(svid - 190)}` : null;
4861
+ if (svid <= 215) return `S${two(svid - 157)}`;
4862
+ if (svid <= 222) return svid - 208 <= 14 ? `I${two(svid - 208)}` : null;
4863
+ if (svid <= 245) return svid - 182 <= 50 ? `C${two(svid - 182)}` : null;
4864
+ return null;
4865
+ }
4866
+ function carrierFreq(sys, code, fcn) {
4867
+ const band = code.charCodeAt(0) - 48;
4868
+ switch (sys) {
4869
+ case "G":
4870
+ case "J":
4871
+ if (band === 1) return 157542e4;
4872
+ if (band === 2) return 12276e5;
4873
+ if (band === 5) return 117645e4;
4874
+ if (band === 6) return 127875e4;
4875
+ return 0;
4876
+ case "R":
4877
+ if (band === 1) return 1602e6 + fcn * 562500;
4878
+ if (band === 2) return 1246e6 + fcn * 437500;
4879
+ if (band === 3) return 1202025e3;
4880
+ return 0;
4881
+ case "E":
4882
+ if (band === 1) return 157542e4;
4883
+ if (band === 5) return 117645e4;
4884
+ if (band === 6) return 127875e4;
4885
+ if (band === 7) return 120714e4;
4886
+ if (band === 8) return 1191795e3;
4887
+ return 0;
4888
+ case "C":
4889
+ if (band === 1) return 157542e4;
4890
+ if (band === 2) return 1561098e3;
4891
+ if (band === 5) return 117645e4;
4892
+ if (band === 6) return 126852e4;
4893
+ if (band === 7) return 120714e4;
4894
+ if (band === 8) return 1191795e3;
4895
+ return 0;
4896
+ case "S":
4897
+ if (band === 1) return 157542e4;
4898
+ if (band === 5) return 117645e4;
4899
+ return 0;
4900
+ case "I":
4901
+ if (band === 1) return 157542e4;
4902
+ if (band === 5) return 117645e4;
4903
+ if (band === 9) return 2492028e3;
4904
+ return 0;
4905
+ default:
4906
+ return 0;
4907
+ }
4908
+ }
4909
+ var ZERO_REF_SLOT = {
4910
+ sigIdx: 0,
4911
+ pr: 0,
4912
+ cp: 0,
4913
+ cn0: 0,
4914
+ lockTimeMs: null
4915
+ };
4916
+ function freshRefEpoch(tow) {
4917
+ return {
4918
+ tow,
4919
+ headers: new Array(7).fill(null),
4920
+ sats: Array.from({ length: 7 }, () => new Array(64))
4921
+ };
4922
+ }
4923
+ function parseSbfMeas(data) {
4924
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
4925
+ const epochs = [];
4926
+ const messageCounts = {};
4927
+ const obsCodes = {};
4928
+ let badCrc = 0;
4929
+ let ref = freshRefEpoch(-1);
4930
+ let curTime = NaN;
4931
+ let curMeas = [];
4932
+ let curSats = [];
4933
+ const flush = () => {
4934
+ if (curMeas.length > 0) {
4935
+ const meas = curMeas.map((m) => {
4936
+ const codes = obsCodes[m.sys] ??= [];
4937
+ if (!codes.includes(m.code)) codes.push(m.code);
4938
+ return {
4939
+ prn: m.prn,
4940
+ code: m.code,
4941
+ pr: m.pr !== 0 ? m.pr : null,
4942
+ cp: m.cp !== 0 ? m.cp : null,
4943
+ doppler: m.doppler,
4944
+ cn0: m.cn0,
4945
+ lockTimeMs: m.lockTimeMs
4946
+ };
4947
+ });
4948
+ epochs.push({ timeMs: curTime, meas });
4949
+ }
4950
+ curMeas = [];
4951
+ curSats = [];
4952
+ };
4953
+ const ensureEpoch = (timeMs) => {
4954
+ if (timeMs !== curTime) {
4955
+ flush();
4956
+ curTime = timeMs;
4957
+ }
4958
+ };
4959
+ const decodeMeas3Ranges = (i2, tow) => {
4960
+ const o = i2 + 8;
4961
+ const constellations = view.getUint16(o + 8, true) & 127;
4962
+ const misc = data[o + 10];
4963
+ const version = data[o + 11];
4964
+ if (version > 31) return;
4965
+ if ((misc & 7) !== 0) return;
4966
+ const prrAvailable = (misc & 8) !== 0;
4967
+ const interval = M3_INTERVALS[misc >> 4];
4968
+ const isRef = tow % interval === 0;
4969
+ const dtow = tow % interval;
4970
+ if (isRef) {
4971
+ ref = freshRefEpoch(tow);
4972
+ } else if (ref.tow !== Math.floor(tow / interval) * interval) {
4973
+ curMeas = [];
4974
+ curSats = [];
4975
+ return;
4976
+ }
4977
+ let idx = o + 12;
4978
+ for (let navsys = 0; navsys < 7; navsys++) {
4979
+ if ((constellations & 1 << navsys) === 0) continue;
4980
+ const sys = M3_SYS[navsys];
4981
+ const useRefHeader = data[idx] === 0;
4982
+ const hdr = useRefHeader ? ref.headers[navsys] ?? new Uint8Array(0) : data.subarray(idx, idx + 32);
4983
+ const BF1 = hdr[0] ?? 0;
4984
+ let nB = BF1 & 7;
4985
+ if (nB === 7) nB = 8;
4986
+ const sigIdxMasterShort = BF1 >> 3 & 15;
4987
+ const sigExclPresent = BF1 >> 7 !== 0;
4988
+ let h = 1;
4989
+ const maskBytes = hdr.subarray(h, h + nB);
4990
+ let nSats = 0;
4991
+ for (const b of maskBytes)
4992
+ for (let k = 0; k < 8; k++) nSats += b >> k & 1;
4993
+ h += nB;
4994
+ let gloFncs = new Uint8Array(0);
4995
+ let bdsLongRange = 0;
4996
+ if (navsys === 1) {
4997
+ gloFncs = hdr.subarray(h, h + (nSats + 1 >> 1));
4998
+ h += nSats + 1 >> 1;
4999
+ } else if (navsys === 3) {
5000
+ bdsLongRange = (hdr[h] ?? 0) | (hdr[h + 1] ?? 0) << 8;
5001
+ h += 2;
5002
+ }
5003
+ const sigExcluded = sigExclPresent ? hdr[h++] ?? 0 : 0;
5004
+ if (isRef) ref.headers[navsys] = data.slice(idx, idx + h);
5005
+ idx += useRefHeader ? 1 : h;
5006
+ const sigTable = [];
5007
+ for (let s = 0; s < 16; s++)
5008
+ if ((sigExcluded & 1 << s) === 0)
5009
+ sigTable.push(M3_SIG_DEFAULT[navsys][s] ?? null);
5010
+ while (sigTable.length < 16) sigTable.push(null);
5011
+ let satCnt = 0;
5012
+ for (let svid = 0; svid < 64 && satCnt < nSats; svid++) {
5013
+ if (((maskBytes[svid >> 3] ?? 0) >> (svid & 7) & 1) === 0) continue;
5014
+ const glofnc = navsys === 1 ? ((gloFncs[satCnt >> 1] ?? 0) >> 4 * (satCnt % 2) & 15) - 8 : 0;
5015
+ const prn = m3Prn(navsys, svid);
5016
+ const prbase = navsys === 3 && (bdsLongRange & 1 << satCnt) !== 0 ? 34e6 : M3_PR_BASE[navsys];
5017
+ const refSat = ref.sats[navsys][svid];
5018
+ const refSlot = (k) => refSat?.slots[k] ?? ZERO_REF_SLOT;
5019
+ const entry = { navsys, svid, prn, slots: [] };
5020
+ const bt = data[idx];
5021
+ let masterSigIdx;
5022
+ let slaveMask;
5023
+ let prRate = 0;
5024
+ let mPr = 0;
5025
+ let mCp = 0;
5026
+ let mCn0 = 0;
5027
+ let mLock = null;
5028
+ let masterCode;
5029
+ let mFreq = 0;
5030
+ if ((bt & 1) === 1) {
5031
+ const BF1m = view.getUint32(idx, true);
5032
+ const prLsb = view.getUint32(idx + 4, true);
5033
+ const cmc = BF1m >>> 1 & 262143;
5034
+ const prMsb = BF1m >>> 19 & 1;
5035
+ const lti3 = BF1m >>> 20 & 7;
5036
+ const cn0 = BF1m >>> 23 & 31;
5037
+ const signalList = BF1m >>> 28 & 15;
5038
+ masterSigIdx = sigIdxMasterShort;
5039
+ slaveMask = signalList << masterSigIdx + 1;
5040
+ masterCode = sigTable[masterSigIdx] ?? null;
5041
+ if (masterCode) {
5042
+ mFreq = carrierFreq(sys, masterCode, glofnc);
5043
+ mPr = prbase + (prLsb + 4294967296 * prMsb) * 1e-3;
5044
+ mCn0 = cn0 + 24;
5045
+ if (cmc !== 0) mCp = mPr / (CLIGHT / mFreq) - 131.072 + cmc * 1e-3;
5046
+ mLock = M3_LOCK_TIME[lti3];
5047
+ }
5048
+ prRate = prrAvailable ? view.getInt16(idx + 8, true) : 0;
5049
+ idx += prrAvailable ? 10 : 8;
5050
+ } else if ((bt & 3) === 0) {
5051
+ const BF1m = view.getUint32(idx, true);
5052
+ const prLsb = view.getUint32(idx + 4, true);
5053
+ const BF2 = view.getUint16(idx + 8, true);
5054
+ const BF3 = data[idx + 10];
5055
+ const prMsb = BF1m >>> 2 & 15;
5056
+ const cmc = BF1m >>> 6 & 4194303;
5057
+ const lti4 = BF1m >>> 28 & 15;
5058
+ const cn0 = BF2 & 63;
5059
+ let signalMask = BF2 >>> 6 & 511;
5060
+ const cont = BF2 >>> 15 & 1;
5061
+ if (cont !== 0) signalMask |= (BF3 & 127) << 9;
5062
+ masterSigIdx = 0;
5063
+ while (masterSigIdx < 32 && (signalMask >> masterSigIdx & 1) === 0)
5064
+ masterSigIdx++;
5065
+ slaveMask = signalMask !== 0 ? signalMask ^ 1 << masterSigIdx : 0;
5066
+ masterCode = sigTable[masterSigIdx] ?? null;
5067
+ if (masterCode) {
5068
+ mFreq = carrierFreq(sys, masterCode, glofnc);
5069
+ const isGpsPCode = navsys === 0 && (masterCode === "1W" || masterCode === "2W");
5070
+ mPr = (prLsb + 4294967296 * prMsb) * 1e-3;
5071
+ mCn0 = isGpsPCode ? cn0 : cn0 + 10;
5072
+ if (cmc !== 0)
5073
+ mCp = mPr / (CLIGHT / mFreq) - 2097.152 + cmc * 1e-3;
5074
+ mLock = M3_LOCK_TIME[lti4];
5075
+ }
5076
+ prRate = prrAvailable ? view.getInt16(idx + 10, true) : 0;
5077
+ idx += (prrAvailable ? 12 : 10) + cont;
5078
+ } else if ((bt & 12) === 12) {
5079
+ const BF1m = data[idx];
5080
+ const BF2 = view.getUint32(idx + 1, true);
5081
+ const prDelta = BF1m >> 4 << 13 | BF2 & 8191;
5082
+ const cn0Delta = BF2 >>> 13 & 7;
5083
+ const cmc = BF2 >>> 16;
5084
+ masterSigIdx = refSlot(0).sigIdx;
5085
+ slaveMask = refSat?.slaveMask ?? 0;
5086
+ masterCode = sigTable[masterSigIdx] ?? null;
5087
+ if (masterCode) {
5088
+ const r = refSlot(0);
5089
+ mFreq = carrierFreq(sys, masterCode, glofnc);
5090
+ mPr = r.pr + Math.trunc((refSat?.prRate ?? 0) * 64 * dtow / 1e3) * 1e-3 + prDelta * 1e-3 - 65.536;
5091
+ mCn0 = r.cn0 - 4 + cn0Delta;
5092
+ if (cmc !== 0)
5093
+ mCp = (mPr - r.pr) / (CLIGHT / mFreq) + r.cp - 32.768 + cmc * 1e-3;
5094
+ mLock = r.lockTimeMs;
5095
+ }
5096
+ idx += 5;
5097
+ } else {
5098
+ const BF1m = view.getUint32(idx, true);
5099
+ const prDelta = BF1m >>> 4 & 16383;
5100
+ const cmc = BF1m >>> 18 & 16383;
5101
+ const cn0Delta = BF1m >>> 2 & 3;
5102
+ masterSigIdx = refSlot(0).sigIdx;
5103
+ slaveMask = refSat?.slaveMask ?? 0;
5104
+ masterCode = sigTable[masterSigIdx] ?? null;
5105
+ if (masterCode) {
5106
+ const r = refSlot(0);
5107
+ mFreq = carrierFreq(sys, masterCode, glofnc);
5108
+ mPr = r.pr + Math.trunc((refSat?.prRate ?? 0) * 64 * dtow / 1e3) * 1e-3 + prDelta * 1e-3 - 8.192;
5109
+ mCn0 = r.cn0 - 1 + cn0Delta;
5110
+ if (cmc !== 0)
5111
+ mCp = (mPr - r.pr) / (CLIGHT / mFreq) + r.cp - 8.192 + cmc * 1e-3;
5112
+ mLock = r.lockTimeMs;
5113
+ }
5114
+ idx += 4;
5115
+ }
5116
+ let masterMeas = null;
5117
+ if (masterCode && prn) {
5118
+ masterMeas = {
5119
+ prn,
5120
+ sys,
5121
+ code: masterCode,
5122
+ freq: mFreq,
5123
+ pr: mPr,
5124
+ cp: mCp,
5125
+ cn0: mCn0,
5126
+ doppler: null,
5127
+ lockTimeMs: mLock
5128
+ };
5129
+ curMeas.push(masterMeas);
5130
+ }
5131
+ entry.slots.push(masterMeas);
5132
+ let newRefSat = null;
5133
+ if (isRef && prn) {
5134
+ newRefSat = {
5135
+ slaveMask,
5136
+ prRate,
5137
+ slots: [
5138
+ {
5139
+ sigIdx: masterSigIdx,
5140
+ pr: mPr,
5141
+ cp: mCp,
5142
+ cn0: mCn0,
5143
+ lockTimeMs: mLock
5144
+ }
5145
+ ]
5146
+ };
5147
+ ref.sats[navsys][svid] = newRefSat;
5148
+ }
5149
+ let slaveCnt = 0;
5150
+ let mask = slaveMask;
5151
+ for (let s = 1; s < 16 && mask !== 0; s++) {
5152
+ if ((mask & 1 << s) === 0) continue;
5153
+ const bt2 = data[idx];
5154
+ const code = sigTable[s] ?? null;
5155
+ const freq = code ? carrierFreq(sys, code, glofnc) : 0;
5156
+ let sPr = 0;
5157
+ let sCp = 0;
5158
+ let sCn0 = 0;
5159
+ let sLock = null;
5160
+ if ((bt2 & 1) === 1) {
5161
+ const BF1s = view.getUint32(idx, true);
5162
+ const BF2s = data[idx + 4];
5163
+ const cmcRes = BF1s >>> 1 & 65535;
5164
+ const prRel = BF1s >>> 17;
5165
+ const lti3 = BF2s & 7;
5166
+ const cn0 = BF2s >> 3;
5167
+ if (code) {
5168
+ sPr = mFreq > freq ? mPr + prRel * 1e-3 - 10 : mPr - prRel * 1e-3 + 10;
5169
+ if (cmcRes !== 0)
5170
+ sCp = sPr / (CLIGHT / freq) + (mCp - mPr / (CLIGHT / mFreq)) * (mFreq / freq) - 32.768 + cmcRes * 1e-3;
5171
+ sCn0 = navsys === 0 && (code === "1W" || code === "2W") ? mCn0 - 3 - cn0 : cn0 + 24;
5172
+ sLock = M3_LOCK_TIME[lti3];
5173
+ }
5174
+ idx += 5;
5175
+ } else if ((bt2 & 3) === 0) {
5176
+ const BF1s = view.getUint32(idx, true);
5177
+ const prLsbRel = view.getUint16(idx + 4, true);
5178
+ const BF3s = data[idx + 6];
5179
+ const cmc = BF1s >>> 2 & 4194303;
5180
+ const lti4 = BF1s >>> 24 & 15;
5181
+ const prMsbRel = BF1s >>> 28 & 7;
5182
+ const cn0 = BF3s & 63;
5183
+ if (code) {
5184
+ sPr = mPr + (prMsbRel * 65536 + prLsbRel) * 1e-3 - 262.144;
5185
+ if (cmc !== 0)
5186
+ sCp = sPr / (CLIGHT / freq) - 2097.152 + cmc * 1e-3;
5187
+ sCn0 = navsys === 0 && (code === "1W" || code === "2W") ? cn0 : cn0 + 10;
5188
+ sLock = M3_LOCK_TIME[lti4];
5189
+ }
5190
+ idx += 7;
5191
+ } else {
5192
+ const BF1s = view.getUint16(idx, true);
5193
+ const dC = data[idx + 2];
5194
+ const dPr = BF1s >>> 2 & 4095;
5195
+ const cn0Delta = BF1s >>> 14;
5196
+ if (code) {
5197
+ const rS = refSlot(slaveCnt + 1);
5198
+ const rM = refSlot(0);
5199
+ sCp = rS.cp + (mCp - rM.cp) * (freq / mFreq) - 0.128 + dC * 1e-3;
5200
+ sPr = rS.pr + (sCp - rS.cp) * (CLIGHT / freq) - 2.048 + dPr * 1e-3;
5201
+ sCn0 = rS.cn0 - 2 + cn0Delta;
5202
+ sLock = rS.lockTimeMs;
5203
+ }
5204
+ idx += 3;
5205
+ }
5206
+ let slaveMeas = null;
5207
+ if (code && prn) {
5208
+ slaveMeas = {
5209
+ prn,
5210
+ sys,
5211
+ code,
5212
+ freq,
5213
+ pr: sPr,
5214
+ cp: sCp,
5215
+ cn0: sCn0,
5216
+ doppler: null,
5217
+ lockTimeMs: sLock
5218
+ };
5219
+ curMeas.push(slaveMeas);
5220
+ }
5221
+ entry.slots.push(slaveMeas);
5222
+ if (newRefSat)
5223
+ newRefSat.slots[slaveCnt + 1] = {
5224
+ sigIdx: s,
5225
+ pr: sPr,
5226
+ cp: sCp,
5227
+ cn0: sCn0,
5228
+ lockTimeMs: sLock
5229
+ };
5230
+ slaveCnt++;
5231
+ mask &= ~(1 << s);
5232
+ }
5233
+ curSats.push(entry);
5234
+ satCnt++;
5235
+ }
5236
+ }
5237
+ };
5238
+ const decodeMeas3CN0 = (i2, len) => {
5239
+ const flags = view.getUint16(i2 + 14, true);
5240
+ if ((flags & 7) !== 0) return;
5241
+ const maxNibbles = (len - 16) * 2;
5242
+ let off = 0;
5243
+ for (const e of curSats) {
5244
+ if (off >= maxNibbles) break;
5245
+ if (!e.prn) continue;
5246
+ for (let k = 0; k < e.slots.length; k++) {
5247
+ const slot = e.slots[k];
5248
+ if (k > 0 && !slot) break;
5249
+ const nib = (data[i2 + 16 + (off >> 1)] ?? 0) >> (off & 1) * 4 & 15;
5250
+ if (slot && slot.cn0 !== null) slot.cn0 += nib * 0.0625 - 0.5;
5251
+ off++;
5252
+ }
5253
+ }
5254
+ };
5255
+ const readPrRate = (base, off) => {
5256
+ const byteAt = (k) => data[base + off + k] ?? 0;
5257
+ const v = (byteAt(0) | byteAt(1) << 8 | byteAt(2) << 16 | byteAt(3) << 24) >>> 0;
5258
+ let value;
5259
+ let size;
5260
+ if ((v & 2) === 0) {
5261
+ value = (v & 255) >>> 2;
5262
+ size = 1;
5263
+ } else if ((v & 6) === 2) {
5264
+ value = (v & 65535) >>> 3;
5265
+ size = 2;
5266
+ } else if ((v & 14) === 6) {
5267
+ value = (v & 16777215) >>> 4;
5268
+ size = 3;
5269
+ } else {
5270
+ value = v >>> 4;
5271
+ size = 4;
5272
+ }
5273
+ if ((v & 1) === 1) value = -value;
5274
+ return { value, size };
5275
+ };
5276
+ const decodeMeas3Doppler = (i2, len) => {
5277
+ const flags = view.getUint16(i2 + 14, true);
5278
+ if ((flags & 7) !== 0) return;
5279
+ let off = 0;
5280
+ for (const e of curSats) {
5281
+ if (off + 16 >= len) break;
5282
+ if (!e.prn) continue;
5283
+ const master = readPrRate(i2 + 16, off);
5284
+ off += master.size;
5285
+ if (master.value === -268435455) continue;
5286
+ const refPrRate = ref.sats[e.navsys][e.svid]?.prRate ?? 0;
5287
+ const m = e.slots[0];
5288
+ const mD = m ? -(master.value + refPrRate * 64) * 1e-3 / (CLIGHT / m.freq) : 0;
5289
+ if (m) m.doppler = mD;
5290
+ for (let k = 1; k < e.slots.length; k++) {
5291
+ const slot = e.slots[k];
5292
+ if (!slot) break;
5293
+ const slave = readPrRate(i2 + 16, off);
5294
+ off += slave.size;
5295
+ if (m)
5296
+ slot.doppler = (mD * (CLIGHT / m.freq) * 1e3 - slave.value) * 1e-3 / (CLIGHT / slot.freq);
5297
+ }
5298
+ }
5299
+ };
5300
+ const decodeMeasEpoch = (i2, len) => {
5301
+ const n1 = data[i2 + 14];
5302
+ const len1 = data[i2 + 15];
5303
+ const len2 = data[i2 + 16];
5304
+ if ((data[i2 + 17] & 128) !== 0) return;
5305
+ const end = i2 + len;
5306
+ let p = i2 + 20;
5307
+ for (let b1 = 0; b1 < n1 && p + 20 <= end; b1++) {
5308
+ const ant = data[p + 1] >> 5;
5309
+ let sig = data[p + 1] & 31;
5310
+ const svid = data[p + 2];
5311
+ const misc = data[p + 3];
5312
+ const info = data[p + 18];
5313
+ const n2 = data[p + 19];
5314
+ let fcn = 0;
5315
+ if (sig === 31) sig = (info >> 3) + 32;
5316
+ else if (sig >= 8 && sig <= 11) fcn = (info >> 3) - 8;
5317
+ const prn = svidToPrn(svid);
5318
+ const sigDef = MEAS2_SIG[sig] ?? null;
5319
+ if (ant !== 0 || !prn || !sigDef || sigDef[0] !== prn[0]) {
5320
+ p += len1 + len2 * n2;
5321
+ continue;
5322
+ }
5323
+ const [sys, code] = sigDef;
5324
+ const freq1 = carrierFreq(sys, code, fcn);
5325
+ const codeLsb = view.getUint32(p + 4, true);
5326
+ const dopplerRaw = view.getInt32(p + 8, true);
5327
+ const carrierLsb = view.getUint16(p + 12, true);
5328
+ const carrierMsb = view.getInt8(p + 14);
5329
+ const cn0Raw = data[p + 15];
5330
+ const lock = view.getUint16(p + 16, true);
5331
+ let p1 = 0;
5332
+ if ((misc & 15) !== 0 || codeLsb !== 0)
5333
+ p1 = (misc & 15) * 4294967296e-3 + codeLsb * 1e-3;
5334
+ const d1 = dopplerRaw !== -2147483648 ? dopplerRaw * 1e-4 : null;
5335
+ let l1 = 0;
5336
+ if (p1 !== 0 && freq1 > 0 && lock !== 65535 && (carrierMsb !== -128 || carrierLsb !== 0))
5337
+ l1 = p1 * freq1 / CLIGHT + carrierMsb * 65.536 + carrierLsb * 1e-3;
5338
+ const cn0 = cn0Raw !== 255 ? cn0Raw * 0.25 + (sig === 1 || sig === 2 ? 0 : 10) : null;
5339
+ curMeas.push({
5340
+ prn,
5341
+ sys,
5342
+ code,
5343
+ freq: freq1,
5344
+ pr: p1,
5345
+ cp: l1,
5346
+ cn0,
5347
+ doppler: d1,
5348
+ lockTimeMs: lock !== 65535 ? lock * 1e3 : null
5349
+ });
5350
+ p += len1;
5351
+ for (let b2 = 0; b2 < n2 && p + 12 <= end; b2++, p += len2) {
5352
+ let sig2 = data[p] & 31;
5353
+ const ant2 = data[p] >> 5;
5354
+ const lock2 = data[p + 1];
5355
+ const cn0Raw2 = data[p + 2];
5356
+ const offsetsMsb = data[p + 3];
5357
+ const carrierMsb2 = view.getInt8(p + 4);
5358
+ const info2 = data[p + 5];
5359
+ if (sig2 === 31) sig2 = (info2 >> 3) + 32;
5360
+ const sigDef2 = MEAS2_SIG[sig2] ?? null;
5361
+ if (ant2 !== 0 || !sigDef2 || sigDef2[0] !== prn[0]) continue;
5362
+ const code2 = sigDef2[1];
5363
+ const freq2 = carrierFreq(sys, code2, fcn);
5364
+ const codeOffMsb = (offsetsMsb & 7) << 29 >> 29;
5365
+ const dopplerOffMsb = offsetsMsb >> 3 << 27 >> 27;
5366
+ const codeOffLsb = view.getUint16(p + 6, true);
5367
+ const carrierLsb2 = view.getUint16(p + 8, true);
5368
+ const dopplerOffLsb = view.getUint16(p + 10, true);
5369
+ let p2 = 0;
5370
+ if (p1 !== 0 && (codeOffMsb !== -4 || codeOffLsb !== 0))
5371
+ p2 = p1 + codeOffMsb * 65.536 + codeOffLsb * 1e-3;
5372
+ let l2 = 0;
5373
+ if (p2 !== 0 && freq2 > 0 && (carrierMsb2 !== -128 || carrierLsb2 !== 0))
5374
+ l2 = p2 * freq2 / CLIGHT + carrierMsb2 * 65.536 + carrierLsb2 * 1e-3;
5375
+ let d2 = null;
5376
+ if (d1 !== null && freq1 > 0 && freq2 > 0 && (dopplerOffMsb !== -16 || dopplerOffLsb !== 0))
5377
+ d2 = d1 * freq2 / freq1 + dopplerOffMsb * 6.5536 + dopplerOffLsb * 1e-4;
5378
+ const cn02 = cn0Raw2 !== 255 ? cn0Raw2 * 0.25 + (sig2 === 1 || sig2 === 2 ? 0 : 10) : null;
5379
+ curMeas.push({
5380
+ prn,
5381
+ sys,
5382
+ code: code2,
5383
+ freq: freq2,
5384
+ pr: p2,
5385
+ cp: l2,
5386
+ cn0: cn02,
5387
+ doppler: d2,
5388
+ lockTimeMs: lock2 !== 255 ? lock2 * 1e3 : null
5389
+ });
5390
+ }
5391
+ }
5392
+ };
5393
+ let i = 0;
5394
+ while (i + 8 <= data.length) {
5395
+ if (data[i] !== 36 || data[i + 1] !== 64) {
5396
+ i++;
5397
+ continue;
5398
+ }
5399
+ const len = view.getUint16(i + 6, true);
5400
+ if (len < 8 || len % 4 !== 0) {
5401
+ i++;
5402
+ continue;
5403
+ }
5404
+ if (i + len > data.length) break;
5405
+ if (crc16(data, i + 4, i + len) !== view.getUint16(i + 2, true)) {
5406
+ badCrc++;
5407
+ i++;
5408
+ continue;
5409
+ }
5410
+ const id = view.getUint16(i + 4, true) & 8191;
5411
+ const key = String(id);
5412
+ messageCounts[key] = (messageCounts[key] ?? 0) + 1;
5413
+ if ((id === 4027 || id === 4109 || id === 4110 || id === 4111) && len >= 16) {
5414
+ const tow = view.getUint32(i + 8, true);
5415
+ const wnc = view.getUint16(i + 12, true);
5416
+ if (tow !== 4294967295 && wnc !== 65535) {
5417
+ ensureEpoch(GPS_EPOCH_MS2 + wnc * MS_PER_WEEK3 + tow);
5418
+ if (id === 4109) decodeMeas3Ranges(i, tow);
5419
+ else if (id === 4110) decodeMeas3CN0(i, len);
5420
+ else if (id === 4111) decodeMeas3Doppler(i, len);
5421
+ else decodeMeasEpoch(i, len);
5422
+ }
5423
+ }
5424
+ i += len;
5425
+ }
5426
+ flush();
5427
+ return { epochs, messageCounts, obsCodes, badCrc };
5428
+ }
5429
+
5430
+ // src/novatel/index.ts
5431
+ var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
5432
+ var MS_PER_WEEK4 = 7 * 864e5;
5433
+ var HDR = 28;
5434
+ var ID_RANGE = 43;
5435
+ var ID_RANGECMP = 140;
5436
+ var ID_GLOEPHEMERIS = 723;
5437
+ var C_LIGHT2 = 299792458;
5438
+ var ADR_ROLL = 8388608;
5439
+ function carrierFreq2(sys, code, gloK) {
5440
+ const band = code[0];
5441
+ switch (sys) {
5442
+ case "G":
5443
+ case "J":
5444
+ return band === "1" ? 157542e4 : band === "2" ? 12276e5 : 117645e4;
5445
+ case "S":
5446
+ return band === "1" ? 157542e4 : 117645e4;
5447
+ case "E":
5448
+ return band === "1" ? 157542e4 : band === "5" ? 117645e4 : band === "7" ? 120714e4 : band === "8" ? 1191795e3 : 127875e4;
5449
+ case "C":
5450
+ return band === "1" ? 157542e4 : band === "2" ? 1561098e3 : band === "5" ? 117645e4 : band === "7" ? 120714e4 : 126852e4;
5451
+ case "R": {
5452
+ if (gloK === null) return 0;
5453
+ if (band === "1") return 1602e6 + gloK * 562500;
5454
+ if (band === "2") return 1246e6 + gloK * 437500;
5455
+ return 1202025e3;
5456
+ }
5457
+ default:
5458
+ return 0;
5459
+ }
5460
+ }
5461
+ function exsign(v, bits) {
5462
+ return v & 1 << bits - 1 ? v - 2 ** bits : v;
5463
+ }
5464
+ function crc32(data, start, len) {
5465
+ let crc = 0;
5466
+ for (let i = start; i < start + len; i++) {
5467
+ crc ^= data[i];
5468
+ for (let j = 0; j < 8; j++) {
5469
+ crc = crc & 1 ? crc >>> 1 ^ 3988292384 : crc >>> 1;
5470
+ }
5471
+ }
5472
+ return crc >>> 0;
5473
+ }
5474
+ var SIGNALS2 = {
5475
+ 0: {
5476
+ 0: ["G", "1C"],
5477
+ 5: ["G", "2P"],
5478
+ 9: ["G", "2W"],
5479
+ 14: ["G", "5Q"],
5480
+ 16: ["G", "1L"],
5481
+ 17: ["G", "2S"]
5482
+ },
5483
+ 1: { 0: ["R", "1C"], 1: ["R", "2C"], 5: ["R", "2P"], 6: ["R", "3Q"] },
5484
+ 2: { 0: ["S", "1C"], 6: ["S", "5I"] },
5485
+ 3: {
5486
+ 1: ["E", "1C"],
5487
+ 2: ["E", "1C"],
5488
+ 6: ["E", "6B"],
5489
+ 7: ["E", "6C"],
5490
+ 12: ["E", "5Q"],
5491
+ 17: ["E", "7Q"],
5492
+ 20: ["E", "8Q"]
5493
+ },
5494
+ 4: {
5495
+ 0: ["C", "2I"],
5496
+ 1: ["C", "7I"],
5497
+ 2: ["C", "6I"],
5498
+ 4: ["C", "2I"],
5499
+ 5: ["C", "7I"],
5500
+ 6: ["C", "6I"],
5501
+ 7: ["C", "1P"],
5502
+ 9: ["C", "5P"],
5503
+ 11: ["C", "7D"]
5504
+ },
5505
+ 5: {
5506
+ 0: ["J", "1C"],
5507
+ 14: ["J", "5Q"],
5508
+ 16: ["J", "1L"],
5509
+ 17: ["J", "2S"],
5510
+ 27: ["J", "6L"]
5511
+ },
5512
+ 6: { 0: ["I", "5A"] }
5513
+ };
5514
+ function parseNovatelRange(data) {
5515
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
5516
+ const epochs = [];
5517
+ const messageCounts = {};
5518
+ const obsCodes = {};
5519
+ let badCrc = 0;
5520
+ const gloFcn = /* @__PURE__ */ new Map();
5521
+ for (let j = 0; j + HDR + 4 <= data.length; j++) {
5522
+ if (data[j] !== 170 || data[j + 1] !== 68 || data[j + 2] !== 18)
5523
+ continue;
5524
+ const hl = data[j + 3];
5525
+ const id = view.getUint16(j + 4, true);
5526
+ const ln = view.getUint16(j + 8, true);
5527
+ if (id !== ID_GLOEPHEMERIS || hl < HDR || j + hl + ln + 4 > data.length)
5528
+ continue;
5529
+ if (crc32(data, j, hl + ln) !== view.getUint32(j + hl + ln, true)) continue;
5530
+ const slot = view.getUint16(j + hl, true) - 37;
5531
+ const k = view.getUint16(j + hl + 2, true) - 7;
5532
+ if (slot >= 1 && slot <= 32) gloFcn.set(slot, k);
5533
+ j += hl + ln + 3;
5534
+ }
5535
+ let i = 0;
5536
+ while (i + HDR + 4 <= data.length) {
5537
+ if (data[i] !== 170 || data[i + 1] !== 68 || data[i + 2] !== 18) {
5538
+ i++;
5539
+ continue;
5540
+ }
5541
+ const hlen = data[i + 3];
5542
+ const msgId = view.getUint16(i + 4, true);
5543
+ const msgLen = view.getUint16(i + 8, true);
5544
+ const total = hlen + msgLen + 4;
5545
+ if (hlen < HDR || i + total > data.length) {
5546
+ i++;
5547
+ continue;
5548
+ }
5549
+ if (crc32(data, i, hlen + msgLen) !== view.getUint32(i + hlen + msgLen, true)) {
5550
+ badCrc++;
5551
+ i++;
5552
+ continue;
5553
+ }
5554
+ messageCounts[msgId] = (messageCounts[msgId] ?? 0) + 1;
5555
+ const binary = (data[i + 6] >> 4 & 3) === 0;
5556
+ const week = view.getUint16(i + 14, true);
5557
+ const towMs = view.getUint32(i + 16, true);
5558
+ if (msgId === ID_RANGECMP && binary && week > 0) {
5559
+ const p = i + hlen;
5560
+ const nobs = view.getUint32(p, true);
5561
+ if (p + 4 + nobs * 24 <= i + hlen + msgLen) {
5562
+ const meas = [];
5563
+ for (let k = 0; k < nobs; k++) {
5564
+ const o = p + 4 + 24 * k;
5565
+ const stat = view.getUint32(o, true);
5566
+ const satsys = stat >>> 16 & 7;
5567
+ const sigtype = stat >>> 21 & 31;
5568
+ const plock = stat >>> 10 & 1;
5569
+ const parity = stat >>> 11 & 1;
5570
+ const clock = stat >>> 12 & 1;
5571
+ const sig = SIGNALS2[satsys]?.[sigtype];
5572
+ if (!sig) continue;
5573
+ let [sysL, code] = sig;
5574
+ let prnNum = data[o + 17];
5575
+ if (sysL === "R") prnNum -= 37;
5576
+ if (sysL === "S" && prnNum >= 183 && prnNum <= 191 && code === "1C") {
5577
+ sysL = "J";
5578
+ code = "1Z";
5579
+ prnNum -= 182;
5580
+ } else if (sysL === "S") {
5581
+ prnNum -= 100;
5582
+ }
5583
+ if (prnNum < 1 || prnNum > 99) continue;
5584
+ if (sysL === "R" && !parity) continue;
5585
+ const gloK = sysL === "R" ? gloFcn.get(prnNum) ?? null : null;
5586
+ const dop = exsign(view.getUint32(o + 4, true) & 268435455, 28) / 256;
5587
+ const psr = (view.getUint32(o + 7, true) >>> 4) / 128 + data[o + 11] * 2097152;
5588
+ let cp = null;
5589
+ const freq = carrierFreq2(sysL, code, gloK);
5590
+ if (freq > 0) {
5591
+ const adr = view.getInt32(o + 12, true) / 256;
5592
+ const rolls = psr * freq / C_LIGHT2 / ADR_ROLL + adr / ADR_ROLL;
5593
+ cp = -adr + ADR_ROLL * Math.floor(rolls + (rolls <= 0 ? -0.5 : 0.5));
5594
+ }
5595
+ const lockt = (view.getUint32(o + 18, true) & 2097151) / 32;
5596
+ const cn0 = ((view.getUint16(o + 20, true) & 1023) >>> 5) + 20;
5597
+ meas.push({
5598
+ prn: `${sysL}${String(prnNum).padStart(2, "0")}`,
5599
+ code,
5600
+ pr: clock ? psr : null,
5601
+ cp: plock ? cp : null,
5602
+ doppler: plock ? dop : null,
5603
+ cn0,
5604
+ lockTimeS: lockt,
5605
+ gloChannel: gloK
5606
+ });
5607
+ const codes = obsCodes[sysL] ??= [];
5608
+ if (!codes.includes(code)) codes.push(code);
5609
+ }
5610
+ epochs.push({
5611
+ timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK4 + towMs,
5612
+ meas
5613
+ });
5614
+ }
5615
+ } else if (msgId === ID_RANGE && binary && week > 0) {
5616
+ const p = i + hlen;
5617
+ const nobs = view.getUint32(p, true);
5618
+ if (p + 4 + nobs * 44 <= i + hlen + msgLen) {
5619
+ const meas = [];
5620
+ for (let k = 0; k < nobs; k++) {
5621
+ const o = p + 4 + 44 * k;
5622
+ const stat = view.getUint32(o + 40, true);
5623
+ const satsys = stat >>> 16 & 7;
5624
+ const sigtype = stat >>> 21 & 31;
5625
+ const plock = stat >>> 10 & 1;
5626
+ const parity = stat >>> 11 & 1;
5627
+ const clock = stat >>> 12 & 1;
5628
+ const sig = SIGNALS2[satsys]?.[sigtype];
5629
+ if (!sig) continue;
5630
+ let [sysL, code] = sig;
5631
+ let prnNum = view.getUint16(o, true);
5632
+ if (sysL === "R") prnNum -= 37;
5633
+ if (sysL === "S" && prnNum >= 183 && prnNum <= 191 && code === "1C") {
5634
+ sysL = "J";
5635
+ code = "1Z";
5636
+ prnNum -= 182;
5637
+ } else if (sysL === "S") {
5638
+ prnNum -= 100;
5639
+ }
5640
+ if (prnNum < 1 || prnNum > 99) continue;
5641
+ if (sysL === "R" && !parity) continue;
5642
+ const prn = `${sysL}${String(prnNum).padStart(2, "0")}`;
5643
+ const gfrq = view.getUint16(o + 2, true);
5644
+ const psr = view.getFloat64(o + 4, true);
5645
+ const adr = view.getFloat64(o + 16, true);
5646
+ const dop = view.getFloat32(o + 28, true);
5647
+ const snr = view.getFloat32(o + 32, true);
5648
+ const lockt = view.getFloat32(o + 36, true);
5649
+ meas.push({
5650
+ prn,
5651
+ code,
5652
+ pr: clock ? psr : null,
5653
+ cp: plock ? -adr : null,
5654
+ doppler: plock ? dop : null,
5655
+ cn0: snr,
5656
+ lockTimeS: lockt,
5657
+ gloChannel: sysL === "R" ? gfrq - 8 : null
5658
+ });
5659
+ const codes = obsCodes[sysL] ??= [];
5660
+ if (!codes.includes(code)) codes.push(code);
5661
+ }
5662
+ epochs.push({
5663
+ timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK4 + towMs,
5664
+ meas
5665
+ });
5666
+ }
5667
+ }
5668
+ i += total;
5669
+ }
5670
+ return { epochs, messageCounts, obsCodes, badCrc };
5671
+ }
5672
+
4594
5673
  // src/orbit/index.ts
4595
5674
  var GM_GPS = 3986005e8;
4596
5675
  var GM_GAL = 3986004418e5;
@@ -4940,10 +6019,10 @@ function selectBest(ephs, timeMs) {
4940
6019
  }
4941
6020
  return best;
4942
6021
  }
4943
- var GPS_EPOCH_MS = START_GPS_TIME.getTime();
4944
- var MS_PER_WEEK2 = 7 * 864e5;
6022
+ var GPS_EPOCH_MS4 = START_GPS_TIME.getTime();
6023
+ var MS_PER_WEEK5 = 7 * 864e5;
4945
6024
  var BDS_EPOCH_MS = START_BDS_TIME.getTime();
4946
- var GAL_EPOCH_MS = GPS_EPOCH_MS + 1024 * MS_PER_WEEK2;
6025
+ var GAL_EPOCH_MS = GPS_EPOCH_MS4 + 1024 * MS_PER_WEEK5;
4947
6026
  function ephInfoToEphemeris(info) {
4948
6027
  const sys = info.prn.charAt(0);
4949
6028
  if (sys === "R") {
@@ -4994,11 +6073,11 @@ function ephInfoToEphemeris(info) {
4994
6073
  } else if (sys === "E") {
4995
6074
  epochMs = GAL_EPOCH_MS;
4996
6075
  } else {
4997
- epochMs = GPS_EPOCH_MS;
4998
- const weeksNow = (info.lastReceived - GPS_EPOCH_MS) / MS_PER_WEEK2;
6076
+ epochMs = GPS_EPOCH_MS4;
6077
+ const weeksNow = (info.lastReceived - GPS_EPOCH_MS4) / MS_PER_WEEK5;
4999
6078
  week += 1024 * Math.round((weeksNow - week) / 1024);
5000
6079
  }
5001
- const tocDate = new Date(epochMs + week * MS_PER_WEEK2 + tocSec * 1e3);
6080
+ const tocDate = new Date(epochMs + week * MS_PER_WEEK5 + tocSec * 1e3);
5002
6081
  return {
5003
6082
  system: sys,
5004
6083
  prn: info.prn,
@@ -8090,10 +9169,13 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
8090
9169
  parseIonex,
8091
9170
  parseNavFile,
8092
9171
  parseNmeaFile,
9172
+ parseNovatelRange,
8093
9173
  parseRinexStream,
9174
+ parseSbfMeas,
8094
9175
  parseSinexBiasDcb,
8095
9176
  parseSourcetable,
8096
9177
  parseSp3,
9178
+ parseUbxRawx,
8097
9179
  phiAltBOC,
8098
9180
  phiBOCc,
8099
9181
  phiBOCs,