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 latency from processing
026         * delays within the system.
027         */
028        System(0),
029        /**
030         * Timestamp as reported by the CANivore.
031         * This timestamp is captured when the CANivore receives the signal value.
032         * <p>
033         * The CANivore is synchronized to the system monotonic clock and benefits
034         * from reduced latency over the {@link TimestampSource#System System} timestamp.
035         * <p>
036         * On the native roboRIO CAN bus, this timestamp is equivalent to the {@link TimestampSource#System System} timestamp.
037         * <p>
038         * When used with CANivore, the only inaccuracy in this measurement is latency
039         * from CAN bus arbitration.
040         */
041        CANivore(1),
042        /**
043         * This timestamp source requires Phoenix Pro.
044         * <p>
045         * Timestamp as reported by the device.
046         * This timestamp is captured when the device transmits the signal value.
047         * Because it is timestamped in the device, it is the most accurate timestamp source.
048         * <p>
049         * This timestamp is synchronized to the CANivore clock, which is itself synchronized
050         * to the system monotonic clock. As a result, this timestamp source requires a CANivore.
051         * <p>
052         * It can be assumed there is no latency between this timestamp and when the data was taken.
053         */
054        Device(2);
055
056        public final int value;
057
058        TimestampSource(int initValue) {
059            this.value = initValue;
060        }
061
062        private static HashMap<Integer, TimestampSource> _map = null;
063        static {
064            _map = new HashMap<Integer, TimestampSource>();
065            for (TimestampSource type : TimestampSource.values()) {
066                _map.put(type.value, type);
067            }
068        }
069
070        /**
071         * Gets TimestampSource from specified value
072         *
073         * @param value Value of TimestampSouce
074         * @return TimestampSource of specified value
075         */
076        public static TimestampSource valueOf(int value) {
077            TimestampSource retval = _map.get(value);
078            if (retval != null)
079                return retval;
080            return TimestampSource.values()[0];
081        }
082    }
083
084    private double time;
085    private TimestampSource source;
086    private boolean valid;
087
088    /**
089     * Construct a new Timestamp for the given source.
090     *
091     * @param time The time in seconds
092     * @param source The timestamp source
093     */
094    Timestamp(double time, TimestampSource source) {
095        this(time, source, true);
096    }
097    /**
098     * Construct a new Timestamp for the given source.
099     *
100     * @param time The time in seconds
101     * @param source The timestamp source
102     * @param valid Whether the timestamp is valid (true by default)
103     */
104    Timestamp(double time, TimestampSource source, boolean valid) {
105        update(time, source, valid);
106    }
107    /**
108     * Construct a new invalid Timestamp.
109     */
110    Timestamp() {
111        this.valid = false;
112    }
113
114    void update(double time, TimestampSource source, boolean valid) {
115        this.time = time;
116        this.source = source;
117        this.valid = valid;
118    }
119
120    /**
121     * Get the time in seconds as reported from this timestamp
122     *
123     * @return Time in seconds
124     */
125    public double getTime() {
126        return time;
127    }
128
129    /**
130     * Get the source of this timestamp
131     *
132     * @return Source of this timestamp
133     */
134    public TimestampSource getSource() {
135        return source;
136    }
137
138    /**
139     * Get the latency of this timestamp compared to now
140     *
141     * @return Difference between now and this timestamp
142     */
143    public double getLatency() {
144        return Utils.getCurrentTimeSeconds() - time;
145    }
146
147    /**
148     * Returns if this Timestamp is valid or not.
149     *
150     * @return true when this is valid
151     */
152    public boolean isValid() {
153        return valid;
154    }
155}