Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9c5b8c7
Update url, GPS encoder
gwbres Sep 7, 2025
b2ffce5
Update url, GPS encoder
gwbres Sep 7, 2025
7c1e546
MSRV 1.72
gwbres Sep 7, 2025
90cd8af
Working on GPS encoding
gwbres Sep 7, 2025
c3506df
improving internal FSM
gwbres Sep 7, 2025
d97a5ff
remove potential panic from decoding process
gwbres Sep 7, 2025
8d3708d
remove potential panic from decoding process
gwbres Sep 7, 2025
9c54154
improved frame2 decoding process
gwbres Sep 7, 2025
47eab5c
improved decoding process
gwbres Sep 7, 2025
501a350
improved decoding process
gwbres Sep 7, 2025
3b59a77
improved decoding process
gwbres Sep 7, 2025
9104aa5
Working on GPS encoding
gwbres Sep 7, 2025
e2f3c70
GPS-How encoding
gwbres Sep 7, 2025
a753096
GPS-1 encoding
gwbres Sep 7, 2025
8ce490b
frame1 encoding
gwbres Sep 11, 2025
2323ab4
URA
gwbres Sep 11, 2025
350e76e
add utility methods
gwbres Sep 11, 2025
188315f
Frame2 encoding
gwbres Sep 11, 2025
23c848c
frame3 encoding
gwbres Sep 11, 2025
6e2cdf3
improve API
gwbres Sep 11, 2025
62f9b50
improve API
gwbres Sep 11, 2025
4b910e7
GPS encoding
gwbres Sep 11, 2025
938ed21
GPS encoding
gwbres Sep 11, 2025
730937e
GPS encoding
gwbres Sep 11, 2025
44ebbfd
docs
gwbres Sep 12, 2025
0755c1b
Reworking decoding and encoding infra
gwbres Sep 12, 2025
594fcb4
preamble search and bin offset
gwbres Sep 14, 2025
23f1cca
preamble search and bin offset
gwbres Sep 14, 2025
9691aef
add GPS/QZSS stream
gwbres Sep 14, 2025
88aef0d
add GPS/QZSS stream
gwbres Sep 14, 2025
6b971c8
encoding
gwbres Sep 18, 2025
072fc04
encoding
gwbres Sep 18, 2025
eda8561
encoding
gwbres Sep 18, 2025
0ee406d
encoding
gwbres Sep 18, 2025
f1897ef
encoding
gwbres Sep 18, 2025
9d986d5
encoding
gwbres Sep 18, 2025
cccb117
update gitignore
gwbres Sep 18, 2025
047bd2a
ajout tests
gwbres Sep 18, 2025
86d1b80
ajout tests
gwbres Sep 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/daily.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- uses: actions-rs/toolchain@v1
name: Install Rust
with:
toolchain: 1.82.0
toolchain: 1.72.0
override: true

- uses: actions-rs/cargo@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- uses: actions-rs/toolchain@v1
name: Install Rust
with:
toolchain: 1.82.0
toolchain: 1.72.0
override: true

- uses: actions-rs/cargo@v1
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ Cargo.lock

*.swo
*.swp
*.rs~
*.txt
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "tools"]
path = tools
url = https://github.com/rtk-rs/tools
[submodule "data"]
path = data
url = [email protected]:nav-solutions/data.git
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "gnss-protos"
version = "0.0.2"
version = "0.1.0"
license = "MPL-2.0"
authors = ["Guillaume W. Bres <[email protected]>"]
description = "GNSS protos encoder and decoder"
homepage = "https://github.com/rtk-rs"
repository = "https://github.com/rtk-rs/gnss-protos"
homepage = "https://github.com/nav-solutions"
repository = "https://github.com/nav-solutions/gnss-protos"
keywords = ["geo", "gps", "galileo"]
categories = ["science", "science::geo", "parsing"]
edition = "2021"
Expand All @@ -16,19 +16,20 @@ exclude = [
]

[features]
default = []
default = ["gps"]

# STD support. Currently only used in test mode.
std = []

# Unlock GPS protocol
# Unlock GPS (+QZSS) protocol
gps = []

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docrs", "--generate-link-to-definition"]

[dependencies]
thiserror = "1"
log = { version = "0.4", optional = true }
num-traits = { version = "0.2", default-features = false }

Expand Down
67 changes: 52 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,71 @@
# GNSS-Protos

[![Rust](https://github.com/rtk-rs/gnss-protos/actions/workflows/rust.yml/badge.svg)](https://github.com/rtk-rs/gnss-protos/actions/workflows/rust.yml)
[![Rust](https://github.com/rtk-rs/gnss-protos/actions/workflows/daily.yml/badge.svg)](https://github.com/rtk-rs/gnss-protos/actions/workflows/daily.yml)
[![Rust](https://github.com/nav-solutions/gnss-protos/actions/workflows/rust.yml/badge.svg)](https://github.com/nav-solutions/gnss-protos/actions/workflows/rust.yml)
[![Rust](https://github.com/nav-solutions/gnss-protos/actions/workflows/daily.yml/badge.svg)](https://github.com/nav-solutions/gnss-protos/actions/workflows/daily.yml)
[![crates.io](https://img.shields.io/crates/v/gnss-protos.svg)](https://crates.io/crates/gnss-protos)
[![crates.io](https://docs.rs/gnss-protos/badge.svg)](https://docs.rs/gnss-protos/badge.svg)

[![License](https://img.shields.io/badge/license-MPL_2.0-orange?style=for-the-badge&logo=mozilla)](https://github.com/rtk-rs/gnss-protos/blob/main/LICENSE)
[![MRSV](https://img.shields.io/badge/MSRV-1.72.0-orange?style=for-the-badge)](https://github.com/rust-lang/rust/releases/tag/1.72.0)
[![License](https://img.shields.io/badge/license-MPL_2.0-orange?style=for-the-badge&logo=mozilla)](https://github.com/nav-solutions/gnss-protos/blob/main/LICENSE)

GNSS-Protos
===========

Ths library offers small and efficient decoders for GNSS protocols.
The idea behind this library is to offer an easy to use, efficient and regrouped
framework to encode & decode GNSS protocols.

This library currently supports the following protos:
You can use this API to learn and go deeper into each protocol, as we strive to document
each data bit correctly (refer to the online API).

- `GPS`: available on `gps` crate feature.
All protocols are gated under a library feature, so you can narrow it down to your use case.

GPS proto
=========
Supported protocols
===================

Available on `gps` crate feature.
- GPS / QZSS protocol available on `gps` crate feature, activated by default.

We support the following GPS frames:
GPS (US) / QZSS (Jap) protocol
==============================

- Ephemeris #1
- Ephemeris #2
- Ephemeris #3
The `gps` library feature activates support of GPS/QZSS protocol.

Currently we support Ephemeris frames 1, 2 and 3, which is sufficient for real-time
navigation (we do not support the Almanach frames).
Frames parity is not fully implemented either.

We provide methods to both encode and decode data frames, and methods
to work from a stream of padded bytes (re-aligned) (2) or a bit stream buffer for real-time interfaces (1):

1. The `GpsDecoder` is the solution when working with real-time GPS/QZSS streams.
It is capable to synchronize itself to the frame start (which is not aligned to a byte).
But you have to manage your buffer and operate the API correctly.
This method returns the number of processed _bits_ (not bytes). You are expected
to discard all processed _bits_ each time you invoke the decoder, not to process
the same frame twice. If you discard bytes not bits, you will inevitably loose messages.

```rust
use gnss_protos::gps::GpsDecoder;

// The decoder does not verify parity at the moment
let mut decoder = GpsDecoder::default();

// Feed one of our test frames into it,
// which is equivalent to real-time acquisition
```

2. `GpsQzssFrame` supports a `decode()` that works with a possibly padded Byte.
This is the prefered option when working with a stream that was already manipulated by a machine
and therefore, re-aligned to bytes. Each byte may have padding (or not). The stream must
start with the sync byte.
We used this approach to interface correctly to U-Blox receivers for example
(that pad and align the frames internally).

```rust
use gnss_protos::gps::GpsDecoder;
```

License
=======

This library is part of the [RTK-rs framework](https://github.com/rtk-rs) which
is delivered under the [Mozilla V2 Public](https://www.mozilla.org/en-US/MPL/2.0) license.
This library is part of the [Nav-solutions framework](https://github.com/nav-solutions) and is
licensed under [Mozilla V2 Public](https://www.mozilla.org/en-US/MPL/2.0) license.
1 change: 1 addition & 0 deletions data
Submodule data added at 2a0ef7
185 changes: 181 additions & 4 deletions src/gps/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,94 @@
#[derive(Debug)]
pub(crate) struct ByteArray<'a> {
slice: &'a [GpsDataByte],
}

impl<'a> ByteArray<'a> {
pub fn new(slice: &'a [GpsDataByte]) -> Self {
Self { slice }
}

/// Converts a slice of MSBF [GpsDataByte]s to [u32] correctly LSB aligned,
/// stripped of termination padding.
pub fn value_u32(&self) -> u32 {
let mut value = 0;

match self.slice[0] {
GpsDataByte::MsbPadded(byte) => {
value |= ((byte & 0x3f) as u32) << 24;
},
GpsDataByte::Byte(byte) => {
value |= (byte as u32) << 24;
},
GpsDataByte::LsbPadded(byte) => {},
}

match self.slice[1] {
GpsDataByte::Byte(byte) => {
value |= (byte as u32) << 16;
},
GpsDataByte::MsbPadded(byte) => {
value >>= 2;
value |= ((byte & 0x3f) as u32) << 16;
},
GpsDataByte::LsbPadded(byte) => {
value >>= 2;
value |= (((byte >> 2) & 0x3f) as u32) << 16;
},
}

match self.slice[2] {
GpsDataByte::Byte(byte) => {
value |= (byte as u32) << 8;
},
GpsDataByte::MsbPadded(byte) => {
value >>= 2;
value |= ((byte & 0x3f) as u32) << 8;
},
GpsDataByte::LsbPadded(byte) => {
value >>= 2;
value |= (((byte >> 2) & 0x3f) as u32) << 8;
},
}

match self.slice[3] {
GpsDataByte::Byte(byte) => {
value |= byte as u32;
},
GpsDataByte::MsbPadded(byte) => {
value >>= 2;
value |= (byte & 0x3f) as u32;
},
GpsDataByte::LsbPadded(byte) => {
value >>= 2;
value |= ((byte >> 2) & 0x3f) as u32;
},
}

value
}
}

#[derive(Debug, Copy, Clone, PartialEq)]
/// [GpsDataByte] aligned to 32 bits
pub enum GpsDataByte {
/// 2-bit MSB padding.
/// Usually used at the beginning or stream termination by computers.
/// Usually used at the beginning or end of GPS word to align GPS stream correctly.
MsbPadded(u8),

/// 2-bit LSB padding.
/// Usually used at the beginning or stream termination by computers.
/// Usually used at the beginning or end of GPS word to align GPS stream correctly.
LsbPadded(u8),

/// Plain byte
/// Plain byte (no padding)
Byte(u8),
}

impl Default for GpsDataByte {
fn default() -> Self {
Self::Byte(0)
}
}

impl core::fmt::LowerExp for GpsDataByte {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expand All @@ -34,3 +110,104 @@ impl GpsDataByte {
Self::LsbPadded((byte & 0xfc) >> 2)
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn bytearray() {
for (bytes, value) in [
(
[
GpsDataByte::MsbPadded(0x00),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
],
0x00000000,
),
(
[
GpsDataByte::MsbPadded(0x90),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
],
0x10000000,
),
(
[
GpsDataByte::MsbPadded(0x10),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
],
0x10000000,
),
(
[
GpsDataByte::MsbPadded(0xB0),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
],
0x30000000,
),
(
[
GpsDataByte::MsbPadded(0x01),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
GpsDataByte::Byte(0x00),
],
0x01000000,
),
(
[
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::MsbPadded(0x01),
],
0x00404041,
),
(
[
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::LsbPadded(0x01),
],
0x00404040,
),
(
[
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::LsbPadded(0x03),
],
0x00404040,
),
(
[
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::Byte(0x01),
GpsDataByte::LsbPadded(0x04),
],
0x00404041,
),
] {
let array = ByteArray::new(&bytes);

let result = array.value_u32();
assert_eq!(
value, result,
"failed to test value 0x{:08X} got 0x{:08X}",
value, result
);
}
}
}
22 changes: 22 additions & 0 deletions src/gps/cdma.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::gps::GpsQzssFrame;

/// CDMA modulator, used to scramble a stream of bits
/// that are then GPS/QZSS compatible.
#[derive(Copy, Clone, PartialEq)]
pub struct CDMA {
/// SV ID
sat_id: u8,
}

impl CDMA {
/// Creates a new [CDMA] modulator ready to scramble a stream of bits
/// for this particular SV-ID
pub fn from_satellite_id(sat_id: u8) -> Self {
Self { sat_id }
}

/// Returns the

/// [CDMA] encode this buffer, ready to transmit
pub fn scramble(buffer: &mut [u8], size: usize) {}
}
Loading
Loading