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.MathUtils;
20  
21  /**
22   * Container for sub-frames 5, page 25.
23   * <p>
24   * Table 20-1, sheet 5 and table 40-1, sheet 5 in
25   * <a href="https://navcen.uscg.gov/sites/default/files/pdf/gps/IS-GPS-200N.pdf">NAVSTAR
26   * GPS Space Segment/Navigation User Segment Interface</a>, IS-GPS-200N, 22 Aug 2022
27   * </p>
28   * @author Luc Maisonobe
29   * @since 12.0
30   */
31  public class SubFrame5B extends SubFrame45 {
32  
33      /** Number of SV health words. */
34      private static final int SVH_WORDS = 6;
35  
36      /** Size of SV health fields per word. */
37      private static final int SVH_FIELDS = 4;
38  
39      /** Index of TOA field. */
40      private static final int TOA = 9;
41  
42      /** Index of Week Number field. */
43      private static final int WEEK_NUMBER = 10;
44  
45      /** Index of reserved field A in word 10. */
46      private static final int RESERVED_A_10 = WEEK_NUMBER + SVH_WORDS * SVH_FIELDS + 1;
47  
48      /** Index of reserved field B in word 10. */
49      private static final int RESERVED_B_10 = RESERVED_A_10 + 1;
50  
51      /** Simple constructor.
52       * @param words raw words
53       */
54      SubFrame5B(final int[] words) {
55  
56          // create raw container
57          super(words, RESERVED_B_10 + 1);
58  
59          // populate container
60          setField(TOA,              3, 14,  8, words);
61          setField(WEEK_NUMBER,      3,  6,  8, words);
62          int fieldIndex = WEEK_NUMBER + 1;
63          for (int i = 0; i < SVH_WORDS; ++i) {
64              for (int j = 0; j < SVH_FIELDS; ++j) {
65                  setField(fieldIndex++, 4 + i, 18 - 6 * j, 6, words);
66              }
67          }
68          setField(RESERVED_A_10, 10, 24,  6, words);
69          setField(RESERVED_B_10, 10,  8, 16, words);
70  
71      }
72  
73      /** Get Time of Almanac.
74       * @return time of almanac (seconds)
75       */
76      public int getTOA() {
77          return getField(TOA) << 12;
78      }
79  
80      /** Get the almanac week number.
81       * @return almanac week number
82       */
83      public int getWeekNumber() {
84          return getField(WEEK_NUMBER);
85      }
86  
87      /** Get the SV Health for a satellite.
88       * @param index in the sub-frame (from 1 to 24, beware it is not the satellite number,
89       * it is also related to {@link #getDataId()})
90       * @return SV health
91       */
92      public int getSvHealth(final int index) {
93          MathUtils.checkRangeInclusive(index, 1, 24);
94          return getField(WEEK_NUMBER + index);
95      }
96  
97      /** Get the reserved field A in word 10.
98       * @return reserved field A in word 10
99       */
100     public int getReservedA10() {
101         return getField(RESERVED_A_10);
102     }
103 
104     /** Get the reserved field B in word 10.
105      * @return reserved field B in word 10
106      */
107     public int getReservedB10() {
108         return getField(RESERVED_B_10);
109     }
110 
111 }