CcsdsUnsegmentedTimeCode.java
- /* Copyright 2002-2025 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.time;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- /** This class represents a CCSDS unsegmented time code.
- * @param <T> type of the date
- * @author Luc Maisonobe
- * @since 12.1
- * @see AbsoluteDate
- * @see FieldAbsoluteDate
- */
- class CcsdsUnsegmentedTimeCode<T> extends AbstractCcsdsTimeCode {
- /** Numerator of scale of the sub-second part (10¹⁸/256ⁿ).
- * @since 13.0
- */
- private static final long[] SUB_SCALE_NUM = new long[] {
- 3906250000000000L, 15258789062500L, 3814697265625L, 3814697265625L, 3814697265625L, 3814697265625L, 3814697265625L
- };
- /** Denominator of scale of the sub-second part (10¹⁸/256ⁿ).
- * @since 13.0
- */
- private static final long[] SUB_SCALE_DEN = new long[] {
- 1L, 1L, 64L, 16384L, 4194304L, 1073741824L, 274877906944L
- };
- /** Epoch part. */
- private final T epoch;
- /** Time part.
- * @since 13.0
- */
- private final TimeOffset time;
- /** Create an instance CCSDS Day Unegmented Time Code (CDS).
- * <p>
- * CCSDS Unsegmented Time Code is defined in the blue book: CCSDS Time Code Format
- * (CCSDS 301.0-B-4) published in November 2010
- * </p>
- * <p>
- * If the date to be parsed is formatted using version 3 of the standard (CCSDS
- * 301.0-B-3 published in 2002) or if the extension of the preamble field introduced
- * in version 4 of the standard is not used, then the {@code preambleField2} parameter
- * can be set to 0.
- * </p>
- * @param preambleField1 first byte of the field specifying the format, often not
- * transmitted in data interfaces, as it is constant for a
- * given data interface
- * @param preambleField2 second byte of the field specifying the format (added in
- * revision 4 of the CCSDS standard in 2010), often not
- * transmitted in data interfaces, as it is constant for a
- * given data interface (value ignored if presence not
- * signaled in {@code preambleField1})
- * @param timeField byte array containing the time code
- * @param agencyDefinedEpoch reference epoch, ignored if the preamble field specifies
- * the {@link DateComponents#CCSDS_EPOCH CCSDS reference epoch} is used
- * (and hence may be null in this case, but then {@code ccsdsEpoch} must be non-null)
- * @param ccsdsEpoch reference epoch, ignored if the preamble field specifies
- * the agency epoch is used (and hence may be null in this case,
- * but then {@code agencyDefinedEpoch} must be non-null).
- */
- CcsdsUnsegmentedTimeCode(final byte preambleField1,
- final byte preambleField2,
- final byte[] timeField,
- final T agencyDefinedEpoch,
- final T ccsdsEpoch) {
- // time code identification and reference epoch
- switch (preambleField1 & 0x70) {
- case 0x10:
- // the reference epoch is CCSDS epoch 1958-01-01T00:00:00 TAI
- epoch = ccsdsEpoch;
- break;
- case 0x20:
- // the reference epoch is agency defined
- if (agencyDefinedEpoch == null) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_MISSING_AGENCY_EPOCH);
- }
- epoch = agencyDefinedEpoch;
- break;
- default :
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_PREAMBLE_FIELD,
- formatByte(preambleField1));
- }
- // time field lengths
- int coarseTimeLength = 1 + ((preambleField1 & 0x0C) >>> 2);
- int fineTimeLength = preambleField1 & 0x03;
- if ((preambleField1 & 0x80) != 0x0) {
- // there is an additional octet in preamble field
- coarseTimeLength += (preambleField2 & 0x60) >>> 5;
- fineTimeLength += (preambleField2 & 0x1C) >>> 2;
- }
- if (timeField.length != coarseTimeLength + fineTimeLength) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_LENGTH_TIME_FIELD,
- timeField.length, coarseTimeLength + fineTimeLength);
- }
- long seconds = 0L;
- for (int i = 0; i < coarseTimeLength; ++i) {
- seconds = seconds * 256L + toUnsigned(timeField[i]);
- }
- long attoSeconds = 0L;
- for (int i = coarseTimeLength; i < timeField.length; ++i) {
- attoSeconds += (toUnsigned(timeField[i]) * SUB_SCALE_NUM[i - coarseTimeLength]) /
- SUB_SCALE_DEN[i - coarseTimeLength];
- }
- time = new TimeOffset(seconds, attoSeconds);
- }
- /** Get the epoch part.
- * @return epoch part
- */
- public T getEpoch() {
- return epoch;
- }
- /** Get the time part.
- * @return time part
- * @since 13.0
- */
- public TimeOffset getTime() {
- return time;
- }
- }