diff --git a/Project.toml b/Project.toml index a91aa3b..85f09f2 100755 --- a/Project.toml +++ b/Project.toml @@ -20,7 +20,7 @@ DataStructures = "0.18, 0.19" Dictionaries = "0.4" DocStringExtensions = "0.6, 0.7, 0.8, 0.9" Downloads = "1" -GNSSSignals = "3.2" +GNSSSignals = "3.3" Random = "1" Test = "1" Tracking = "2" diff --git a/docs/src/api.md b/docs/src/api.md index 0b8d6cd..20c57ee 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -35,6 +35,22 @@ reset_decoder_state is_sat_healthy ``` +## Signal Metadata + +`GNSSSignals.get_data_frequency` is extended for [`GNSSDecoderState`](@ref): it +returns the navigation-message symbol rate of the signal the decoder demodulates +(e.g. `50 Hz` for GPS L1 C/A, `100 Hz` for GPS L5-I, `50 Hz` for GPS L2C-M). It +forwards to the corresponding signal's rate in GNSSSignals, so the value stays +single-sourced. Dispatch is on the constants type, which keeps decoders that +share a data container distinct — GPS L5-I and L2C-M both decode into +`GPSCNAVData` but report their own rates. + +```julia +using GNSSDecoder, GNSSSignals +get_data_frequency(GPSL5IDecoderState(1)) # 100 Hz +get_data_frequency(GPSL2CMDecoderState(1)) # 50 Hz +``` + ## Shared Utilities Signal-independent building blocks used across the decoders (CRC-24Q, the diff --git a/src/galileo/e1b.jl b/src/galileo/e1b.jl index 63d9588..9226c27 100644 --- a/src/galileo/e1b.jl +++ b/src/galileo/e1b.jl @@ -575,6 +575,13 @@ function GNSSDecoderState(system::GalileoE1B_BOC11, prn) GalileoE1BDecoderState(prn) end +# Both the full CBOC E1B and its BOC(1,1) approximation decode into +# `GalileoE1BConstants` and carry the identical 250 Hz I/NAV symbol stream, so a +# single method keyed on the constants type serves both. Forwarded from +# GNSSSignals (see `src/gps/l1ca.jl`). +GNSSSignals.get_data_frequency(::GNSSDecoderState{<:Any,GalileoE1BConstants}) = + get_data_frequency(GalileoE1B) + """ $(TYPEDSIGNATURES) diff --git a/src/galileo/e5a.jl b/src/galileo/e5a.jl index 78d5ddd..ae40450 100644 --- a/src/galileo/e5a.jl +++ b/src/galileo/e5a.jl @@ -528,6 +528,11 @@ function GNSSDecoderState(system::GalileoE5aI, prn) GalileoE5aDecoderState(prn) end +# F/NAV symbol rate, forwarded from GNSSSignals (see `src/gps/l1ca.jl`). The +# decoder runs on the E5a-I data component, so the rate is E5a-I's. +GNSSSignals.get_data_frequency(::GNSSDecoderState{<:Any,GalileoE5aConstants}) = + get_data_frequency(GalileoE5aI) + """ $(TYPEDSIGNATURES) diff --git a/src/gps/l1c_d.jl b/src/gps/l1c_d.jl index b8de33d..47874e2 100644 --- a/src/gps/l1c_d.jl +++ b/src/gps/l1c_d.jl @@ -750,6 +750,10 @@ function GNSSDecoderState(system::GPSL1C_D, prn) GPSL1C_DDecoderState(prn) end +# Nav-message symbol rate, forwarded from GNSSSignals (see `src/gps/l1ca.jl`). +GNSSSignals.get_data_frequency(::GNSSDecoderState{<:Any,GPSL1C_DConstants}) = + get_data_frequency(GPSL1C_D) + """ $(TYPEDSIGNATURES) diff --git a/src/gps/l1ca.jl b/src/gps/l1ca.jl index eec7141..1bc7511 100755 --- a/src/gps/l1ca.jl +++ b/src/gps/l1ca.jl @@ -529,6 +529,13 @@ function GNSSDecoderState(system::GPSL1CA, prn) GPSL1CADecoderState(prn) end +# Navigation-message symbol rate of the signal this decoder demodulates, +# forwarded from GNSSSignals so the rate stays single-sourced. Dispatched on the +# constants type, which is 1:1 with the signal (and is what tells apart decoders +# that share a data type — see the GPS CNAV note in `src/gps/l5.jl`). +GNSSSignals.get_data_frequency(::GNSSDecoderState{<:Any,GPSL1CAConstants}) = + get_data_frequency(GPSL1CA) + """ $(TYPEDSIGNATURES) diff --git a/src/gps/l2c.jl b/src/gps/l2c.jl index 30339ef..07d0262 100644 --- a/src/gps/l2c.jl +++ b/src/gps/l2c.jl @@ -92,6 +92,11 @@ function GNSSDecoderState(system::GPSL2CM, prn) GPSL2CMDecoderState(prn) end +# L2C-M's CNAV symbol rate; keyed on the constants type so it stays distinct from +# L5-I despite sharing `GPSCNAVData` (see `src/gps/l5.jl`). +GNSSSignals.get_data_frequency(::GNSSDecoderState{<:Any,GPSL2CMConstants}) = + get_data_frequency(GPSL2CM) + """ $(TYPEDSIGNATURES) diff --git a/src/gps/l5.jl b/src/gps/l5.jl index 9b1e7d4..b761f02 100644 --- a/src/gps/l5.jl +++ b/src/gps/l5.jl @@ -72,6 +72,13 @@ function GNSSDecoderState(system::GPSL5I, prn) GPSL5IDecoderState(prn) end +# GPS CNAV rides on both L5-I (100 sps) and L2C-M (50 sps) but decodes into a +# single `GPSCNAVData`, so the symbol rate is keyed on the constants type +# (`GPSL5IConstants` vs `GPSL2CMConstants`) — the only thing that tells the two +# decoders apart. Forwarded from GNSSSignals (see `src/gps/l1ca.jl`). +GNSSSignals.get_data_frequency(::GNSSDecoderState{<:Any,GPSL5IConstants}) = + get_data_frequency(GPSL5I) + """ $(TYPEDSIGNATURES) diff --git a/test/data_frequency.jl b/test/data_frequency.jl new file mode 100644 index 0000000..5212744 --- /dev/null +++ b/test/data_frequency.jl @@ -0,0 +1,26 @@ +@testset "Navigation-message data frequency" begin + # `get_data_frequency` on a decoder state forwards to the GNSSSignals data + # rate of the signal it demodulates, so a decoder state can report its own + # nav-message symbol rate without the caller re-deriving which signal it is. + signal_of_state = [ + (GPSL1CADecoderState(1), GPSL1CA), + (GPSL1C_DDecoderState(1), GPSL1C_D), + (GPSL5IDecoderState(1), GPSL5I), + (GPSL2CMDecoderState(1), GPSL2CM), + (GalileoE1BDecoderState(1), GalileoE1B), + (GalileoE5aDecoderState(1), GalileoE5aI), + ] + for (state, signal) in signal_of_state + @test get_data_frequency(state) == get_data_frequency(signal) + end + + # GPS L5-I and L2C-M share `GPSCNAVData` but run at different symbol rates; + # dispatch on the constants type must keep them distinct. + @test get_data_frequency(GPSL5IDecoderState(1)) != + get_data_frequency(GPSL2CMDecoderState(1)) + + # The E1B BOC(1,1) approximation decodes the identical I/NAV stream, so its + # decoder reports the same rate as full E1B. + @test get_data_frequency(GNSSDecoder.GNSSDecoderState(GalileoE1B_BOC11(), 1)) == + get_data_frequency(GalileoE1B) +end diff --git a/test/runtests.jl b/test/runtests.jl index 51cfc81..a47b47f 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -33,6 +33,7 @@ end end include("gnss_supertype.jl") + include("data_frequency.jl") include("bit_fiddling.jl") include("gpsl1.jl") include("gps_l1c_d.jl")