001/*
002 * Copyright (C) Cross The Road Electronics.  All rights reserved.
003 * License information can be found in CTRE_LICENSE.txt
004 * For support and suggestions contact support@ctr-electronics.com or file
005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
006 */
007package com.ctre.phoenix6;
008
009import java.util.HashMap;
010
011/**
012 * Information about the timestamp of a signal.
013 */
014public class Timestamp {
015
016    /**
017     * Source of the timestamp.
018     */
019    public enum TimestampSource {
020        /**
021         * Timestamp as reported by the system.
022         * This timestamp is captured when the system receives the signal value.
023         * <p>
024         * This timestamp is present on all systems and is guaranteed to be monotonic.
025         * However, this timestamp is the least accurate due to processing delays within the system.
026         */
027        System(0),
028        /**
029         * Timestamp as reported by the CANivore.
030         * This timestamp is captured when the CANivore receives the signal value.
031         * <p>
032         * The CANivore is synchronized to the system monotonic clock and benefits
033         * from reduced latency over the {@link TimestampSource#System System} timestamp.
034         * <p>
035         * On the native roboRIO CAN bus, this timestamp is equivalent to the {@link TimestampSource#System System} timestamp.
036         * <p>
037         * When used with CANivore, the only inaccuracy in this measurement is latency
038         * from CAN bus arbitration.
039         */
040        CANivore(1),
041        /**
042         * This timestamp source requires Phoenix Pro.
043         * <p>
044         * Timestamp as reported by the device.
045         * This timestamp is captured when the device transmits the signal value.
046         * Because it is timestamped in the device, it is the most accurate timestamp source.
047         * <p>
048         * This timestamp is synchronized to the CANivore clock, which is itself synchronized
049         * to the system monotonic clock. As a result, this timestamp source requires a CANivore.
050         * <p>
051         * It can be assumed there is no latency between this timestamp and when the data was taken.
052         */
053        Device(2);
054
055        public final int value;
056
057        TimestampSource(int initValue) {
058            this.value = initValue;
059        }
060
061        private static HashMap<Integer, TimestampSource> _map = null;
062        static {
063            _map = new HashMap<Integer, TimestampSource>();
064            for (TimestampSource type : TimestampSource.values()) {
065                _map.put(type.value, type);
066            }
067        }
068
069        /**
070         * Gets TimestampSource from specified value
071         *
072         * @param value Value of TimestampSouce
073         * @return TimestampSource of specified value
074         */
075        public static TimestampSource valueOf(int value) {
076            TimestampSource retval = _map.get(value);
077            if (retval != null)
078                return retval;
079            return TimestampSource.values()[0];
080        }
081    }
082
083    private double time;
084    private TimestampSource source;
085    private boolean valid;
086
087    /**
088     * Construct a new Timestamp for the given source.
089     *
090     * @param time The time in seconds
091     * @param source The timestamp source
092     */
093    Timestamp(double time, TimestampSource source) {
094        this(time, source, true);
095    }
096    /**
097     * Construct a new Timestamp for the given source.
098     *
099     * @param time The time in seconds
100     * @param source The timestamp source
101     * @param valid Whether the timestamp is valid (true by default)
102     */
103    Timestamp(double time, TimestampSource source, boolean valid) {
104        update(time, source, valid);
105    }
106    /**
107     * Construct a new invalid Timestamp.
108     */
109    Timestamp() {
110        this.valid = false;
111    }
112
113    void update(double time, TimestampSource source, boolean valid) {
114        this.time = time;
115        this.source = source;
116        this.valid = valid;
117    }
118
119    /**
120     * Get the time in seconds as reported from this timestamp
121     *
122     * @return Time in seconds
123     */
124    public double getTime() {
125        return time;
126    }
127
128    /**
129     * Get the source of this timestamp
130     *
131     * @return Source of this timestamp
132     */
133    public TimestampSource getSource() {
134        return source;
135    }
136
137    /**
138     * Get the latency of this timestamp compared to now
139     *
140     * @return Difference between now and this timestamp
141     */
142    public double getLatency() {
143        return Utils.getCurrentTimeSeconds() - time;
144    }
145
146    /**
147     * Returns if this Timestamp is valid or not.
148     *
149     * @return true when this is valid
150     */
151    public boolean isValid() {
152        return valid;
153    }
154}