1use crate::error::{Error, Result};
38use crate::id::GnssSystem;
39
40use super::bits::{BitReader, BitWriter, OutOfInput};
41use super::DecodeResult;
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
45pub enum MsmKind {
46 Msm4,
48 Msm7,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub struct MsmHeader {
56 pub reference_station_id: u16,
58 pub epoch_time: u32,
62 pub multiple_message: bool,
64 pub iods: u8,
66 pub reserved: u8,
68 pub clock_steering: u8,
70 pub external_clock: u8,
72 pub divergence_free_smoothing: bool,
74 pub smoothing_interval: u8,
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq)]
80pub struct MsmSatellite {
81 pub id: u8,
84 pub rough_range_ms: u8,
87 pub rough_range_mod1: u16,
89 pub extended_info: Option<u8>,
92 pub rough_phase_range_rate_m_s: Option<i16>,
94}
95
96#[derive(Clone, Copy, Debug, PartialEq, Eq)]
98pub struct MsmSignal {
99 pub satellite_id: u8,
101 pub signal_id: u8,
103 pub fine_pseudorange: i32,
106 pub fine_phase_range: i32,
109 pub lock_time_indicator: u16,
112 pub half_cycle_ambiguity: bool,
114 pub cnr: u16,
117 pub fine_phase_range_rate: Option<i16>,
119}
120
121impl MsmSignal {
122 pub fn minimum_lock_time_ms(&self, kind: MsmKind) -> Option<u32> {
128 super::lli::minimum_lock_time_ms(kind, self.lock_time_indicator)
129 }
130}
131
132#[derive(Clone, Debug, PartialEq, Eq)]
134pub struct MsmMessage {
135 pub message_number: u16,
137 pub system: GnssSystem,
139 pub kind: MsmKind,
141 pub header: MsmHeader,
143 pub satellites: Vec<MsmSatellite>,
145 pub signals: Vec<MsmSignal>,
147}
148
149pub(crate) fn msm_kind(message_number: u16) -> Option<(GnssSystem, MsmKind)> {
154 if !(1071..=1137).contains(&message_number) {
155 return None;
156 }
157 let group = (message_number - 1071) / 10;
158 let system = match group {
159 0 => GnssSystem::Gps,
160 1 => GnssSystem::Glonass,
161 2 => GnssSystem::Galileo,
162 3 => GnssSystem::Sbas,
163 4 => GnssSystem::Qzss,
164 5 => GnssSystem::BeiDou,
165 6 => GnssSystem::Navic,
166 _ => return None,
167 };
168 let kind = match message_number % 10 {
169 4 => MsmKind::Msm4,
170 7 => MsmKind::Msm7,
171 _ => return None,
172 };
173 Some((system, kind))
174}
175
176pub(crate) fn is_supported_msm(message_number: u16) -> bool {
178 msm_kind(message_number).is_some()
179}
180
181impl MsmMessage {
182 pub fn decode(body: &[u8]) -> Result<Self> {
184 Self::decode_inner(body).map_err(Into::into)
185 }
186
187 pub(crate) fn decode_inner(body: &[u8]) -> DecodeResult<Self> {
188 let mut r = BitReader::new(body);
189 let message_number = r.u(12)? as u16;
190 let (system, kind) = msm_kind(message_number).ok_or_else(|| {
191 Error::Parse(format!(
192 "message {message_number} is not a supported MSM4/MSM7 type"
193 ))
194 })?;
195
196 let header = MsmHeader {
197 reference_station_id: r.u(12)? as u16,
198 epoch_time: r.u(30)? as u32,
199 multiple_message: r.flag()?,
200 iods: r.u(3)? as u8,
201 reserved: r.u(7)? as u8,
202 clock_steering: r.u(2)? as u8,
203 external_clock: r.u(2)? as u8,
204 divergence_free_smoothing: r.flag()?,
205 smoothing_interval: r.u(3)? as u8,
206 };
207
208 let satellite_mask = r.u(64)?;
209 let signal_mask = r.u(32)? as u32;
210 let sat_ids = set_bits(satellite_mask, 64);
211 let sig_ids = set_bits_u32(signal_mask);
212
213 let nsat = sat_ids.len();
214 let nsig = sig_ids.len();
215
216 let mut cell_present = Vec::with_capacity(nsat * nsig);
218 for _ in 0..nsat * nsig {
219 cell_present.push(r.flag()?);
220 }
221
222 let mut rough_range_ms = Vec::with_capacity(nsat);
224 for _ in 0..nsat {
225 rough_range_ms.push(r.u(8)? as u8);
226 }
227 let extended_info = if kind == MsmKind::Msm7 {
228 let mut v = Vec::with_capacity(nsat);
229 for _ in 0..nsat {
230 v.push(Some(r.u(4)? as u8));
231 }
232 v
233 } else {
234 vec![None; nsat]
235 };
236 let mut rough_range_mod1 = Vec::with_capacity(nsat);
237 for _ in 0..nsat {
238 rough_range_mod1.push(r.u(10)? as u16);
239 }
240 let rough_prr = if kind == MsmKind::Msm7 {
241 let mut v = Vec::with_capacity(nsat);
242 for _ in 0..nsat {
243 v.push(Some(r.i(14)? as i16));
244 }
245 v
246 } else {
247 vec![None; nsat]
248 };
249
250 let satellites: Vec<MsmSatellite> = (0..nsat)
251 .map(|s| MsmSatellite {
252 id: sat_ids[s],
253 rough_range_ms: rough_range_ms[s],
254 rough_range_mod1: rough_range_mod1[s],
255 extended_info: extended_info[s],
256 rough_phase_range_rate_m_s: rough_prr[s],
257 })
258 .collect();
259
260 let cells = active_cells(&sat_ids, &sig_ids, &cell_present);
262 let ncell = cells.len();
263
264 let signals = match kind {
266 MsmKind::Msm4 => {
267 let fine_pr = read_vec(&mut r, ncell, |rr| rr.i(15).map(|v| v as i32))?;
268 let fine_ph = read_vec(&mut r, ncell, |rr| rr.i(22).map(|v| v as i32))?;
269 let lock = read_vec(&mut r, ncell, |rr| rr.u(4).map(|v| v as u16))?;
270 let half = read_vec(&mut r, ncell, |rr| rr.flag())?;
271 let cnr = read_vec(&mut r, ncell, |rr| rr.u(6).map(|v| v as u16))?;
272 cells
273 .iter()
274 .enumerate()
275 .map(|(c, &(sat, sig))| MsmSignal {
276 satellite_id: sat,
277 signal_id: sig,
278 fine_pseudorange: fine_pr[c],
279 fine_phase_range: fine_ph[c],
280 lock_time_indicator: lock[c],
281 half_cycle_ambiguity: half[c],
282 cnr: cnr[c],
283 fine_phase_range_rate: None,
284 })
285 .collect()
286 }
287 MsmKind::Msm7 => {
288 let fine_pr = read_vec(&mut r, ncell, |rr| rr.i(20).map(|v| v as i32))?;
289 let fine_ph = read_vec(&mut r, ncell, |rr| rr.i(24).map(|v| v as i32))?;
290 let lock = read_vec(&mut r, ncell, |rr| rr.u(10).map(|v| v as u16))?;
291 let half = read_vec(&mut r, ncell, |rr| rr.flag())?;
292 let cnr = read_vec(&mut r, ncell, |rr| rr.u(10).map(|v| v as u16))?;
293 let fine_prr = read_vec(&mut r, ncell, |rr| rr.i(15).map(|v| v as i16))?;
294 cells
295 .iter()
296 .enumerate()
297 .map(|(c, &(sat, sig))| MsmSignal {
298 satellite_id: sat,
299 signal_id: sig,
300 fine_pseudorange: fine_pr[c],
301 fine_phase_range: fine_ph[c],
302 lock_time_indicator: lock[c],
303 half_cycle_ambiguity: half[c],
304 cnr: cnr[c],
305 fine_phase_range_rate: Some(fine_prr[c]),
306 })
307 .collect()
308 }
309 };
310
311 Ok(Self {
312 message_number,
313 system,
314 kind,
315 header,
316 satellites,
317 signals,
318 })
319 }
320
321 pub fn encode(&self) -> Vec<u8> {
323 let mut w = BitWriter::new();
324 w.push_u(u64::from(self.message_number), 12);
325 w.push_u(u64::from(self.header.reference_station_id), 12);
326 w.push_u(u64::from(self.header.epoch_time), 30);
327 w.push_flag(self.header.multiple_message);
328 w.push_u(u64::from(self.header.iods), 3);
329 w.push_u(u64::from(self.header.reserved), 7);
330 w.push_u(u64::from(self.header.clock_steering), 2);
331 w.push_u(u64::from(self.header.external_clock), 2);
332 w.push_flag(self.header.divergence_free_smoothing);
333 w.push_u(u64::from(self.header.smoothing_interval), 3);
334
335 let mut sat_ids: Vec<u8> = self.satellites.iter().map(|s| s.id).collect();
337 sat_ids.sort_unstable();
338 let mut satellite_mask: u64 = 0;
339 for &id in &sat_ids {
340 satellite_mask |= 1u64 << (64 - u32::from(id));
341 }
342
343 let mut sig_ids: Vec<u8> = self.signals.iter().map(|s| s.signal_id).collect();
345 sig_ids.sort_unstable();
346 sig_ids.dedup();
347 let mut signal_mask: u32 = 0;
348 for &id in &sig_ids {
349 signal_mask |= 1u32 << (32 - u32::from(id));
350 }
351
352 w.push_u(satellite_mask, 64);
353 w.push_u(u64::from(signal_mask), 32);
354
355 let mut ordered_cells: Vec<(u8, u8)> = Vec::new();
357 for &sat in &sat_ids {
358 for &sig in &sig_ids {
359 let present = self
360 .signals
361 .iter()
362 .any(|s| s.satellite_id == sat && s.signal_id == sig);
363 w.push_flag(present);
364 if present {
365 ordered_cells.push((sat, sig));
366 }
367 }
368 }
369
370 let sat_by_id = |id: u8| self.satellites.iter().find(|s| s.id == id);
372 for &id in &sat_ids {
373 let sat = sat_by_id(id);
374 w.push_u(u64::from(sat.map_or(0, |s| s.rough_range_ms)), 8);
375 }
376 if self.kind == MsmKind::Msm7 {
377 for &id in &sat_ids {
378 let ext = sat_by_id(id).and_then(|s| s.extended_info).unwrap_or(0);
379 w.push_u(u64::from(ext), 4);
380 }
381 }
382 for &id in &sat_ids {
383 let sat = sat_by_id(id);
384 w.push_u(u64::from(sat.map_or(0, |s| s.rough_range_mod1)), 10);
385 }
386 if self.kind == MsmKind::Msm7 {
387 for &id in &sat_ids {
388 let prr = sat_by_id(id)
389 .and_then(|s| s.rough_phase_range_rate_m_s)
390 .unwrap_or(0);
391 w.push_i(i64::from(prr), 14);
392 }
393 }
394
395 let cell_signal = |sat: u8, sig: u8| {
397 self.signals
398 .iter()
399 .find(|s| s.satellite_id == sat && s.signal_id == sig)
400 .expect("ordered cell must reference an existing signal")
401 };
402 let ordered: Vec<&MsmSignal> = ordered_cells
403 .iter()
404 .map(|&(sat, sig)| cell_signal(sat, sig))
405 .collect();
406
407 match self.kind {
408 MsmKind::Msm4 => {
409 for s in &ordered {
410 w.push_i(i64::from(s.fine_pseudorange), 15);
411 }
412 for s in &ordered {
413 w.push_i(i64::from(s.fine_phase_range), 22);
414 }
415 for s in &ordered {
416 w.push_u(u64::from(s.lock_time_indicator), 4);
417 }
418 for s in &ordered {
419 w.push_flag(s.half_cycle_ambiguity);
420 }
421 for s in &ordered {
422 w.push_u(u64::from(s.cnr), 6);
423 }
424 }
425 MsmKind::Msm7 => {
426 for s in &ordered {
427 w.push_i(i64::from(s.fine_pseudorange), 20);
428 }
429 for s in &ordered {
430 w.push_i(i64::from(s.fine_phase_range), 24);
431 }
432 for s in &ordered {
433 w.push_u(u64::from(s.lock_time_indicator), 10);
434 }
435 for s in &ordered {
436 w.push_flag(s.half_cycle_ambiguity);
437 }
438 for s in &ordered {
439 w.push_u(u64::from(s.cnr), 10);
440 }
441 for s in &ordered {
442 w.push_i(i64::from(s.fine_phase_range_rate.unwrap_or(0)), 15);
443 }
444 }
445 }
446
447 w.into_bytes()
448 }
449}
450
451fn read_vec<T>(
453 r: &mut BitReader<'_>,
454 n: usize,
455 mut f: impl FnMut(&mut BitReader<'_>) -> std::result::Result<T, OutOfInput>,
456) -> std::result::Result<Vec<T>, OutOfInput> {
457 let mut v = Vec::with_capacity(n);
458 for _ in 0..n {
459 v.push(f(r)?);
460 }
461 Ok(v)
462}
463
464fn set_bits(mask: u64, n: u32) -> Vec<u8> {
467 let mut ids = Vec::new();
468 for i in 0..n {
469 if (mask >> (n - 1 - i)) & 1 == 1 {
470 ids.push((i + 1) as u8);
471 }
472 }
473 ids
474}
475
476fn set_bits_u32(mask: u32) -> Vec<u8> {
478 let mut ids = Vec::new();
479 for i in 0..32u32 {
480 if (mask >> (31 - i)) & 1 == 1 {
481 ids.push((i + 1) as u8);
482 }
483 }
484 ids
485}
486
487fn active_cells(sat_ids: &[u8], sig_ids: &[u8], cell_present: &[bool]) -> Vec<(u8, u8)> {
489 let nsig = sig_ids.len();
490 let mut cells = Vec::new();
491 for (si, &sat) in sat_ids.iter().enumerate() {
492 for (gi, &sig) in sig_ids.iter().enumerate() {
493 if cell_present[si * nsig + gi] {
494 cells.push((sat, sig));
495 }
496 }
497 }
498 cells
499}