001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. All Rights Reserved.                        */
003    /* Open Source Software - may be modified and shared by FRC teams. The code   */
004    /* must be accompanied by the FIRST BSD license file in the root directory of */
005    /* the project.                                                               */
006    /*----------------------------------------------------------------------------*/
007    package edu.wpi.first.wpilibj;
008    
009    import edu.wpi.first.wpilibj.fpga.tWatchdog;
010    import edu.wpi.first.wpilibj.parsing.IUtility;
011    
012    /**
013     * Watchdog timer class.
014     * The watchdog timer is designed to keep the robots safe. The idea is that the robot program must
015     * constantly "feed" the watchdog otherwise it will shut down all the motor outputs. That way if a
016     * program breaks, rather than having the robot continue to operate at the last known speed, the
017     * motors will be shut down.
018     *
019     * This is serious business.  Don't just disable the watchdog.  You can't afford it!
020     *
021     * http://thedailywtf.com/Articles/_0x2f__0x2f_TODO_0x3a__Uncomment_Later.aspx
022     */
023    public class Watchdog extends SensorBase implements IUtility{
024    
025        private static Watchdog m_instance;
026        private tWatchdog m_fpgaWatchdog;
027        /**
028         * Default expiration for the watchdog in seconds
029         */
030        public static final double kDefaultWatchdogExpiration = .5;
031    
032        /**
033         * The Watchdog is born.
034         */
035        protected Watchdog() {
036            m_fpgaWatchdog = new tWatchdog();
037            setExpiration(Watchdog.kDefaultWatchdogExpiration);
038            setEnabled(true);
039        }
040    
041        /**
042         *  Get an instance of the watchdog
043         * @return an instance of the watchdog
044         */
045        public static synchronized Watchdog getInstance() {
046            if (m_instance == null) {
047                m_instance = new Watchdog();
048            }
049            return m_instance;
050        }
051    
052        /**
053         * Throw the dog a bone.
054         *
055         * When everything is going well, you feed your dog when you get home.
056         * Let's hope you don't drive your car off a bridge on the way home...
057         * Your dog won't get fed and he will starve to death.
058         *
059         * By the way, it's not cool to ask the neighbor (some random task) to
060         * feed your dog for you.  He's your responsibility!
061         */
062        public void feed() {
063            tWatchdog.strobeFeed();
064        }
065    
066        /**
067         * Put the watchdog out of its misery.
068         *
069         * Don't wait for your dying robot to starve when there is a problem.
070         * Kill it quickly, cleanly, and humanely.
071         */
072        public void kill() {
073            tWatchdog.strobeKill();
074        }
075    
076        /**
077         * Read how long it has been since the watchdog was last fed.
078         *
079         * @return The number of seconds since last meal.
080         */
081        public double getTimer() {
082            long timer = tWatchdog.readTimer();
083            return timer / (kSystemClockTicksPerMicrosecond * 1e6);
084        }
085    
086        /**
087         * Read what the current expiration is.
088         *
089         * @return The number of seconds before starvation following a meal (watchdog starves if it doesn't eat this often).
090         */
091        public double getExpiration() {
092            long expiration = tWatchdog.readExpiration();
093            return (double)expiration / (kSystemClockTicksPerMicrosecond * 1e6);
094        }
095    
096        /**
097         * Configure how many seconds your watchdog can be neglected before it starves to death.
098         *
099         * @param expiration The number of seconds before starvation following a meal (watchdog starves if it doesn't eat this often).
100         */
101        public void setExpiration(double expiration) {
102            tWatchdog.writeExpiration((int) (expiration * (kSystemClockTicksPerMicrosecond * 1e6)));
103        }
104    
105        /**
106         * Find out if the watchdog is currently enabled or disabled (mortal or immortal).
107         *
108         * @return Enabled or disabled.
109         */
110        public boolean getEnabled() {
111            return !tWatchdog.readImmortal();
112        }
113    
114        /**
115         * Enable or disable the watchdog timer.
116         *
117         * When enabled, you must keep feeding the watchdog timer to
118         * keep the watchdog active, and hence the dangerous parts
119         * (motor outputs, etc.) can keep functioning.
120         * When disabled, the watchdog is immortal and will remain active
121         * even without being fed.  It will also ignore any kill commands
122         * while disabled.
123         *
124         * @param enabled Enable or disable the watchdog.
125         */
126        public void setEnabled(final boolean enabled) {
127            tWatchdog.writeImmortal(!enabled);
128        }
129    
130        /**
131         * Check in on the watchdog and make sure he's still kicking.
132         *
133         * This indicates that your watchdog is allowing the system to operate.
134         * It is still possible that the network communications is not allowing the
135         * system to run, but you can check this to make sure it's not your fault.
136         * Check isSystemActive() for overall system status.
137         *
138         * If the watchdog is disabled, then your watchdog is immortal.
139         *
140         * @return Is the watchdog still alive?
141         */
142        public boolean isAlive() {
143            return tWatchdog.readStatus_Alive();
144        }
145    
146        /**
147         * Check on the overall status of the system.
148         *
149         * @return Is the system active (i.e. PWM motor outputs, etc. enabled)?
150         */
151        public boolean isSystemActive() {
152            return tWatchdog.readStatus_SystemActive();
153        }
154    }