1 /* Copyright 2002-2024 CS GROUP
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.time;
18
19 import org.orekit.errors.OrekitException;
20 import org.orekit.errors.OrekitMessages;
21
22 /** This class represents a CCSDS unsegmented time code.
23 * @param <T> type of the date
24 * @author Luc Maisonobe
25 * @since 12.1
26 * @see AbsoluteDate
27 * @see FieldAbsoluteDate
28 */
29 class CcsdsUnsegmentedTimeCode<T> extends AbstractCcsdsTimeCode {
30
31 /** Epoch part. */
32 private final T epoch;
33
34 /** Seconds part. */
35 private final long seconds;
36
37 /** Sub-second part. */
38 private final double subSecond;
39
40 /** Create an instance CCSDS Day Unegmented Time Code (CDS).
41 * <p>
42 * CCSDS Unsegmented Time Code is defined in the blue book: CCSDS Time Code Format
43 * (CCSDS 301.0-B-4) published in November 2010
44 * </p>
45 * <p>
46 * If the date to be parsed is formatted using version 3 of the standard (CCSDS
47 * 301.0-B-3 published in 2002) or if the extension of the preamble field introduced
48 * in version 4 of the standard is not used, then the {@code preambleField2} parameter
49 * can be set to 0.
50 * </p>
51 * @param preambleField1 first byte of the field specifying the format, often not
52 * transmitted in data interfaces, as it is constant for a
53 * given data interface
54 * @param preambleField2 second byte of the field specifying the format (added in
55 * revision 4 of the CCSDS standard in 2010), often not
56 * transmitted in data interfaces, as it is constant for a
57 * given data interface (value ignored if presence not
58 * signaled in {@code preambleField1})
59 * @param timeField byte array containing the time code
60 * @param agencyDefinedEpoch reference epoch, ignored if the preamble field specifies
61 * the {@link DateComponents#CCSDS_EPOCH CCSDS reference epoch} is used
62 * (and hence may be null in this case)
63 * @param ccsdsEpoch reference epoch, ignored if the preamble field specifies
64 * the agency epoch is used.
65 */
66 CcsdsUnsegmentedTimeCode(final byte preambleField1,
67 final byte preambleField2,
68 final byte[] timeField,
69 final T agencyDefinedEpoch,
70 final T ccsdsEpoch) {
71
72 // time code identification and reference epoch
73 switch (preambleField1 & 0x70) {
74 case 0x10:
75 // the reference epoch is CCSDS epoch 1958-01-01T00:00:00 TAI
76 epoch = ccsdsEpoch;
77 break;
78 case 0x20:
79 // the reference epoch is agency defined
80 if (agencyDefinedEpoch == null) {
81 throw new OrekitException(OrekitMessages.CCSDS_DATE_MISSING_AGENCY_EPOCH);
82 }
83 epoch = agencyDefinedEpoch;
84 break;
85 default :
86 throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_PREAMBLE_FIELD,
87 formatByte(preambleField1));
88 }
89
90 // time field lengths
91 int coarseTimeLength = 1 + ((preambleField1 & 0x0C) >>> 2);
92 int fineTimeLength = preambleField1 & 0x03;
93
94 if ((preambleField1 & 0x80) != 0x0) {
95 // there is an additional octet in preamble field
96 coarseTimeLength += (preambleField2 & 0x60) >>> 5;
97 fineTimeLength += (preambleField2 & 0x1C) >>> 2;
98 }
99
100 if (timeField.length != coarseTimeLength + fineTimeLength) {
101 throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_LENGTH_TIME_FIELD,
102 timeField.length, coarseTimeLength + fineTimeLength);
103 }
104
105 long s = 0L;
106 for (int i = 0; i < coarseTimeLength; ++i) {
107 s = s * 256 + toUnsigned(timeField[i]);
108 }
109 seconds = s;
110
111 double sub = 0;
112 for (int i = timeField.length - 1; i >= coarseTimeLength; --i) {
113 sub = (sub + toUnsigned(timeField[i])) / 256;
114 }
115 subSecond = sub;
116
117 }
118
119 /** Get the epoch part.
120 * @return epoch part
121 */
122 public T getEpoch() {
123 return epoch;
124 }
125
126 /** Get the seconds part.
127 * @return seconds part
128 */
129 public long getSeconds() {
130 return seconds;
131 }
132
133 /** Get the sub-second part.
134 * @return sub-second part
135 */
136 public double getSubSecond() {
137 return subSecond;
138 }
139
140 }