1   /* Copyright 2022-2025 Thales Alenia Space
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.gnss.rflink.gps;
18  
19  import org.hipparchus.util.FastMath;
20  import org.orekit.gnss.metric.parser.Units;
21  import org.orekit.utils.units.Unit;
22  
23  /**
24   * Container for sub-frames 4, page 18.
25   * <p>
26   * Table 40-1, sheet 8 in
27   * <a href="https://navcen.uscg.gov/sites/default/files/pdf/gps/IS-GPS-200N.pdf">NAVSTAR
28   * GPS Space Segment/Navigation User Segment Interface</a>, IS-GPS-200N, 22 Aug 2022
29   * </p>
30   * @author Luc Maisonobe
31   * @since 12.0
32   */
33  public class SubFrame4D extends SubFrame45 {
34  
35      /** Seconds per semi-circle. */
36      private static final Unit S_PER_SC = Unit.SECOND.divide("s/sc", Units.SEMI_CIRCLE);
37  
38      /** Seconds per semi-circle². */
39      private static final Unit S_PER_SC2 = S_PER_SC.divide("s/sc²", Units.SEMI_CIRCLE);
40  
41      /** Seconds per semi-circle³. */
42      private static final Unit S_PER_SC3 = S_PER_SC2.divide("s/sc³", Units.SEMI_CIRCLE);
43  
44      /** Index of α₀ field. */
45      private static final int ALPHA0 = 9;
46  
47      /** Index of α₁ field. */
48      private static final int ALPHA1 = 10;
49  
50      /** Index of α₂ field. */
51      private static final int ALPHA2 = 11;
52  
53      /** Index of α₃ field. */
54      private static final int ALPHA3 = 12;
55  
56      /** Index of β₀ field. */
57      private static final int BETA0 = 13;
58  
59      /** Index of β₁ field. */
60      private static final int BETA1 = 14;
61  
62      /** Index of β₂ field. */
63      private static final int BETA2 = 15;
64  
65      /** Index of β₃ field. */
66      private static final int BETA3 = 16;
67  
68      /** Index of A₁ field. */
69      private static final int A1 = 17;
70  
71      /** Index of A0 field. */
72      private static final int A0 = 18;
73  
74      /** Index of TOT field. */
75      private static final int TOT = 19;
76  
77      /** Index of Week Number T field. */
78      private static final int WEEK_NUMBER_T = 20;
79  
80      /** Index of ΔtLS field. */
81      private static final int DELTA_T_LS = 21;
82  
83      /** Index of Week Number LSF field. */
84      private static final int WEEK_NUMBER_LSF = 22;
85  
86      /** Index of DN field. */
87      private static final int DN = 23;
88  
89      /** Index of ΔtLSF field. */
90      private static final int DELTA_T_LSF = 24;
91  
92      /** Index of reserved field in word 10. */
93      private static final int RESERVED_10 = 25;
94  
95      /** Simple constructor.
96       * @param words raw words
97       */
98      SubFrame4D(final int[] words) {
99  
100         // create raw container
101         super(words, RESERVED_10 + 1);
102 
103         // populate container
104         setField(ALPHA0,           3, 14,  8, words);
105         setField(ALPHA1,           3,  6,  8, words);
106         setField(ALPHA2,           4, 22,  8, words);
107         setField(ALPHA3,           4, 14,  8, words);
108         setField(BETA0,            4,  6,  8, words);
109         setField(BETA1,            5, 22,  8, words);
110         setField(BETA2,            5, 14,  8, words);
111         setField(BETA3,            5,  6,  8, words);
112         setField(A1,               6,  6, 24, words);
113         setField(A0,               7,  6, 24, 8, 22, 8, words);
114         setField(TOT,              8, 14,  8, words);
115         setField(WEEK_NUMBER_T,    8,  6,  8, words);
116         setField(DELTA_T_LS,       9, 22,  8, words);
117         setField(WEEK_NUMBER_LSF,  9, 14,  8, words);
118         setField(DN,               9,  6,  8, words);
119         setField(DELTA_T_LSF,     10, 22,  8, words);
120         setField(RESERVED_10,     10,  8, 14, words);
121 
122     }
123 
124     /** Get α₀ field.
125      * @return α₀ field (second).
126      */
127     public double getAlpha0() {
128         return FastMath.scalb((double) getField(ALPHA0), -30);
129     }
130 
131     /** Get α₁ field.
132      * @return α₁ field (second/rad).
133      */
134     public double getAlpha1() {
135         return S_PER_SC.toSI(FastMath.scalb((double) getField(ALPHA1), -27));
136     }
137 
138     /** Get α₂ field.
139      * @return α₂ field (second/rad²).
140      */
141     public double getAlpha2() {
142         return S_PER_SC2.toSI(FastMath.scalb((double) getField(ALPHA2), -24));
143     }
144 
145     /** Get α₃ field.
146      * @return α₃ field (second/rad³)
147      */
148     public double getAlpha3() {
149         return S_PER_SC3.toSI(FastMath.scalb((double) getField(ALPHA3), -24));
150     }
151 
152     /** Get β₀ field.
153      * @return β₀ field (second)
154      */
155     public double getBeta0() {
156         return FastMath.scalb((double) getField(BETA0), 11);
157     }
158 
159     /** Get β₁ field.
160      * @return β₁ field (second/rad)
161      */
162     public double getBeta1() {
163         return S_PER_SC.toSI(FastMath.scalb((double) getField(BETA1), 14));
164     }
165 
166     /** Get β₂ field.
167      * @return β₂ field (second/rad²)
168      */
169     public double getBeta2() {
170         return S_PER_SC2.toSI(FastMath.scalb((double) getField(BETA2), 16));
171     }
172 
173     /** Get β₃ field.
174      * @return β₃ field (second/rad³)
175      */
176     public double getBeta3() {
177         return S_PER_SC3.toSI(FastMath.scalb((double) getField(BETA3), 16));
178     }
179 
180     /** Get A₁ field.
181      * @return A₁ field (second/second).
182      */
183     public double getA1() {
184         return FastMath.scalb((double) getField(A1), -50);
185     }
186 
187     /** Get A0 field.
188      * @return A0 field (seconds).
189      */
190     public double getA0() {
191         return FastMath.scalb((double) getField(A0), -30);
192     }
193 
194     /** Get TOT field.
195      * @return TOT field. */
196     public int getTot() {
197         return getField(TOT) << 12;
198     }
199 
200     /** Get Week Number T field.
201      * @return Week Number T field. */
202     public int getWeekNumberT() {
203         return getField(WEEK_NUMBER_T);
204     }
205 
206     /** Get ΔtLS field.
207      * @return ΔtLS field. */
208     public int getDeltaTLs() {
209         return getField(DELTA_T_LS);
210     }
211 
212     /** Get Week Number LSF field.
213      * @return Week Number LSF field. */
214     public int getWeekNumberLsf() {
215         return getField(WEEK_NUMBER_LSF);
216     }
217 
218     /** Get DN field.
219      * @return DN field. */
220     public int getDn() {
221         return getField(DN);
222     }
223 
224     /** Get ΔtLSF field.
225      * @return ΔtLSF field. */
226     public int getDeltaTLsf() {
227         return getField(DELTA_T_LSF);
228     }
229 
230     /** Get reserved field in word 10.
231      * @return reserved field in word 10. */
232     public int getReserved10() {
233         return getField(RESERVED_10);
234     }
235 
236 }