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.phoenixpro;
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 is not currently implemented in this version of 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        update(time, source, true);
095    }
096    /**
097     * Construct a new invalid Timestamp.
098     */
099    Timestamp() {
100        this.valid = false;
101    }
102
103    void update(double time, TimestampSource source, boolean valid) {
104        this.time = time;
105        this.source = source;
106        this.valid = valid;
107    }
108
109    /**
110     * Get the time in seconds as reported from this timestamp
111     *
112     * @return Time in seconds
113     */
114    public double getTime() {
115        return time;
116    }
117
118    /**
119     * Get the source of this timestamp
120     *
121     * @return Source of this timestamp
122     */
123    public TimestampSource getSource() {
124        return source;
125    }
126
127    /**
128     * Get the latency of this timestamp compared to now
129     *
130     * @return Difference between now and this timestamp
131     */
132    public double getLatency() {
133        return Utils.getCurrentTimeSeconds() - time;
134    }
135
136    /**
137     * Returns if this Timestamp is valid or not.
138     *
139     * @return true when this is valid
140     */
141    public boolean isValid() {
142        return valid;
143    }
144}