Orbis.GNSS.Navigation.LNAV (Orbis v0.9.0)

Copy Markdown View Source

GPS L1 C/A LNAV navigation message synthesis and decoding (subframes 1-3).

The legacy navigation (LNAV) message is the data stream modulated onto the GPS L1 C/A signal at 50 bits per second. Its structure is defined in IS-GPS-200 (Section 20.3): the message is organized into 1500-bit frames, each frame being five 300-bit subframes, and each subframe being ten 30-bit words. Every word carries 24 source data bits (most significant first) followed by 6 parity bits.

This module covers the clock and ephemeris subframes:

  • Subframe 1 - SV clock correction and health (IS-GPS-200 Table 20-I).
  • Subframe 2 - first half of the ephemeris (IS-GPS-200 Table 20-II).
  • Subframe 3 - second half of the ephemeris (IS-GPS-200 Table 20-III).

The first word of every subframe is the telemetry (TLM) word; the second is the hand-over word (HOW). Both are described in IS-GPS-200 Section 20.3.3.

Words and bits

A subframe is represented as a flat list of 300 bits (0/1), most significant bit first, with the ten words concatenated in transmission order. word_length/0 is 30 and subframe_length/0 is 300.

Parameters and units

encode/2 and decode/1 exchange an Orbis.GNSS.Navigation.LNAV.Ephemeris struct whose fields hold the natural engineering-unit values (the products of the transmitted integers and their IS-GPS-200 scale factors). See that struct's documentation for the per-field units. Angular ephemeris quantities use semicircles (and semicircles/second), the harmonic correction terms use radians, distances use meters, and clock/time quantities use seconds, exactly as tabulated in IS-GPS-200.

Parity

The 6 parity bits of each word are produced by the (32, 26) Hamming code of IS-GPS-200 Section 20.3.5.2 and Table 20-XIV, including the rule that the two trailing parity bits of the previous word (D29*, D30*) feed the current word and that D30* complements the 24 transmitted data bits. The last two data bits of the HOW and of word 10 are solved so that those words' D29/D30 parity bits are zero, per IS-GPS-200 Section 20.3.3.2. At the start of each subframe the previous parity bits are seeded to zero, producing self-consistent stand-alone subframes.

Examples

iex> Orbis.GNSS.Navigation.LNAV.word_length()
30

iex> Orbis.GNSS.Navigation.LNAV.subframe_length()
300

iex> Orbis.GNSS.Navigation.LNAV.preamble()
139

Summary

Functions

Decodes LNAV subframes 1-3 back into the engineering-unit parameter struct.

Encodes clock and ephemeris parameters into LNAV subframes 1-3.

Computes the 6 parity bits of a word (IS-GPS-200 Table 20-XIV).

Verifies the parity of a single 30-bit word.

The 8-bit TLM preamble 1000 1011 as an integer (IS-GPS-200 Section 20.3.3.1).

Extracts the 3-bit subframe ID from a hand-over word.

Bit length of a single LNAV subframe (IS-GPS-200 Section 20.3.2).

Extracts the 17-bit time-of-week count from a hand-over word.

Bit length of a single LNAV word (IS-GPS-200 Section 20.3.2).

Functions

decode(map)

@spec decode(%{
  required(1) => [0 | 1],
  required(2) => [0 | 1],
  required(3) => [0 | 1]
}) ::
  {:ok, Orbis.GNSS.Navigation.LNAV.Ephemeris.t()} | {:error, term()}

Decodes LNAV subframes 1-3 back into the engineering-unit parameter struct.

Accepts %{1 => bits, 2 => bits, 3 => bits} of 300-bit subframes. Parity is verified on all 30 words first; a failure returns {:error, {:parity_failed, subframe, word}} (word is 1-based). On success returns {:ok, %Orbis.GNSS.Navigation.LNAV.Ephemeris{}}.

encode(params, opts \\ [])

@spec encode(
  Orbis.GNSS.Navigation.LNAV.Ephemeris.t(),
  keyword()
) ::
  {:ok,
   %{required(1) => [0 | 1], required(2) => [0 | 1], required(3) => [0 | 1]}}
  | {:error, term()}

Encodes clock and ephemeris parameters into LNAV subframes 1-3.

Returns {:ok, %{1 => bits, 2 => bits, 3 => bits}} where each value is a flat list of 300 bits (most significant first). Out-of-range parameters yield {:error, {:out_of_range, field, value}}; this function never raises on bad input.

Options

  • :tow - the 17-bit time-of-week count placed in each HOW (0..131071, default 0).
  • :alert - HOW alert flag (0/1, default 0).
  • :anti_spoof - HOW anti-spoof flag (0/1, default 0).
  • :integrity - TLM integrity status flag (0/1, default 0).
  • :tlm_message - 14-bit TLM message field (default 0).

parity(data24, d29_prev, d30_prev)

@spec parity([0 | 1], 0 | 1, 0 | 1) :: [0 | 1]

Computes the 6 parity bits of a word (IS-GPS-200 Table 20-XIV).

data24 is the list of 24 source data bits (most significant first, before the D30* complementation). d29_prev and d30_prev are the two trailing parity bits of the previous word. Returns [D25, D26, D27, D28, D29, D30].

parity_valid?(word30, d29_prev, d30_prev)

@spec parity_valid?([0 | 1], 0 | 1, 0 | 1) :: boolean()

Verifies the parity of a single 30-bit word.

word30 is the 30-bit word as transmitted (data bits possibly complemented by D30*, followed by 6 received parity bits). d29_prev/d30_prev are the previous word's trailing parity bits. Returns true when the recomputed parity matches the received parity.

preamble()

@spec preamble() :: 139

The 8-bit TLM preamble 1000 1011 as an integer (IS-GPS-200 Section 20.3.3.1).

Examples

iex> Orbis.GNSS.Navigation.LNAV.preamble()
139

subframe_id(bits)

@spec subframe_id([0 | 1]) :: 1..5

Extracts the 3-bit subframe ID from a hand-over word.

Accepts a 30-bit HOW word or a full 300-bit subframe. Returns the subframe identifier carried in HOW bits 20-22 (IS-GPS-200 Section 20.3.3.2).

Examples

iex> {:ok, sfs} = Orbis.GNSS.Navigation.LNAV.encode(Orbis.GNSS.Navigation.LNAV.Ephemeris.example(), tow: 0)
iex> Orbis.GNSS.Navigation.LNAV.subframe_id(sfs[2])
2

subframe_length()

@spec subframe_length() :: 300

Bit length of a single LNAV subframe (IS-GPS-200 Section 20.3.2).

Examples

iex> Orbis.GNSS.Navigation.LNAV.subframe_length()
300

tow(bits)

@spec tow([0 | 1]) :: non_neg_integer()

Extracts the 17-bit time-of-week count from a hand-over word.

Accepts either a 30-bit HOW word or a full 300-bit subframe (whose word 2 is the HOW). The returned value is the truncated Z-count carried in the HOW (units of 6 seconds), per IS-GPS-200 Section 20.3.3.2.

Examples

iex> {:ok, sfs} = Orbis.GNSS.Navigation.LNAV.encode(Orbis.GNSS.Navigation.LNAV.Ephemeris.example(), tow: 12345)
iex> Orbis.GNSS.Navigation.LNAV.tow(sfs[1])
12345

word_length()

@spec word_length() :: 30

Bit length of a single LNAV word (IS-GPS-200 Section 20.3.2).

Examples

iex> Orbis.GNSS.Navigation.LNAV.word_length()
30