001package edu.wpi.first.wpilibj;
002
003import java.nio.ByteBuffer;
004import java.nio.ByteOrder;
005
006import edu.wpi.first.wpilibj.SensorBase;
007import edu.wpi.first.wpilibj.hal.CompressorJNI;
008import edu.wpi.first.wpilibj.hal.HALUtil;
009import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
010import edu.wpi.first.wpilibj.tables.ITable;
011
012/**
013 * Class for operating the PCM (Pneumatics compressor module)
014 * The PCM automatically will run in close-loop mode by default whenever a Solenoid object is 
015 * created. For most cases the Compressor object does not need to be
016 * instantiated or used in a robot program.
017 * 
018 * This class is only required in cases where more detailed status or to enable/disable
019 * closed loop control. Note: you cannot operate the compressor directly from this class as
020 * doing so would circumvent the safety provided in using the pressure switch and closed
021 * loop control. You can only turn off closed loop control, thereby stopping the compressor
022 * from operating.
023 */
024public class Compressor extends SensorBase implements LiveWindowSendable {
025        private ByteBuffer m_pcm;
026
027        /**
028         * Create an instance of the Compressor
029         * @param pcmId
030         *              The PCM CAN device ID. Most robots that use PCM will have a single module. Use this
031         *              for supporting a second module other than the default.
032         */
033        public Compressor(int pcmId) {
034                initCompressor(pcmId);
035        }
036
037        /**
038         * Create an instance of the Compressor
039         * Makes a new instance of the compressor using the default PCM ID (0). Additional modules can be
040         * supported by making a new instance and specifying the CAN ID
041         */
042        public Compressor() {
043                initCompressor(getDefaultSolenoidModule());
044        }
045
046        private void initCompressor(int module) {
047                m_table = null;
048
049                m_pcm = CompressorJNI.initializeCompressor((byte)module);
050        }
051
052        /**
053         * Start the compressor running in closed loop control mode
054         * Use the method in cases where you would like to manually stop and start the compressor
055         * for applications such as conserving battery or making sure that the compressor motor
056         * doesn't start during critical operations.
057         */
058        public void start() {
059                setClosedLoopControl(true);
060        }
061
062        /**
063         * Stop the compressor from running in closed loop control mode.
064         * Use the method in cases where you would like to manually stop and start the compressor
065         * for applications such as conserving battery or making sure that the compressor motor
066         * doesn't start during critical operations.
067         */
068        public void stop() {
069                setClosedLoopControl(false);
070        }
071
072        /**
073         * Get the enabled status of the compressor
074         * @return true if the compressor is on
075         */
076        public boolean enabled() {
077                ByteBuffer status = ByteBuffer.allocateDirect(4);
078                status.order(ByteOrder.LITTLE_ENDIAN);
079
080                boolean on = CompressorJNI.getCompressor(m_pcm, status.asIntBuffer());
081                HALUtil.checkStatus(status.asIntBuffer());
082
083                return on;
084        }
085
086        /**
087         * Get the current pressure switch value
088         * @return true if the pressure is low by reading the pressure switch that is plugged into the PCM
089         */
090        public boolean getPressureSwitchValue() {
091                ByteBuffer status = ByteBuffer.allocateDirect(4);
092                status.order(ByteOrder.LITTLE_ENDIAN);
093
094                boolean on = CompressorJNI.getPressureSwitch(m_pcm, status.asIntBuffer());
095                HALUtil.checkStatus(status.asIntBuffer());
096
097                return on;
098        }
099
100        /**
101         * Get the current being used by the compressor
102         * @return current consumed in amps for the compressor motor
103         */
104        public float getCompressorCurrent() {
105                ByteBuffer status = ByteBuffer.allocateDirect(4);
106                status.order(ByteOrder.LITTLE_ENDIAN);
107
108                float current = CompressorJNI.getCompressorCurrent(m_pcm, status.asIntBuffer());
109                HALUtil.checkStatus(status.asIntBuffer());
110
111                return current;
112        }
113
114        /**
115         * Set the PCM in closed loop control mode
116         * @param on
117         *                      If true sets the compressor to be in closed loop control mode otherwise
118         *                      normal operation of the compressor is disabled.
119         */
120        public void setClosedLoopControl(boolean on) {
121                ByteBuffer status = ByteBuffer.allocateDirect(4);
122                status.order(ByteOrder.LITTLE_ENDIAN);
123
124                CompressorJNI.setClosedLoopControl(m_pcm, on, status.asIntBuffer());
125                HALUtil.checkStatus(status.asIntBuffer());
126        }
127
128        /**
129         * Gets the current operating mode of the PCM
130         * @return true if compressor is operating on closed-loop mode, otherwise return false.
131         */
132        public boolean getClosedLoopControl() {
133                ByteBuffer status = ByteBuffer.allocateDirect(4);
134                status.order(ByteOrder.LITTLE_ENDIAN);
135
136                boolean on = CompressorJNI.getClosedLoopControl(m_pcm, status.asIntBuffer());
137                HALUtil.checkStatus(status.asIntBuffer());
138
139                return on;
140        }
141
142        /**
143         * @return true if PCM is in fault state : Compressor Drive is 
144         *                      disabled due to compressor current being too high.
145         */
146        public boolean getCompressorCurrentTooHighFault() {
147                ByteBuffer status = ByteBuffer.allocateDirect(4);
148                status.order(ByteOrder.LITTLE_ENDIAN);
149
150                boolean retval = CompressorJNI.getCompressorCurrentTooHighFault(m_pcm, status.asIntBuffer());
151                HALUtil.checkStatus(status.asIntBuffer());
152
153                return retval;
154        }
155        /**
156         * @return true if PCM sticky fault is set : Compressor Drive is 
157         *                      disabled due to compressor current being too high.
158         */
159        public boolean getCompressorCurrentTooHighStickyFault() {
160                ByteBuffer status = ByteBuffer.allocateDirect(4);
161                status.order(ByteOrder.LITTLE_ENDIAN);
162
163                boolean retval = CompressorJNI.getCompressorCurrentTooHighStickyFault(m_pcm, status.asIntBuffer());
164                HALUtil.checkStatus(status.asIntBuffer());
165
166                return retval;
167        }
168        /**
169         * @return true if PCM sticky fault is set : Compressor output 
170         *                      appears to be shorted.
171         */
172        public boolean getCompressorShortedStickyFault() {
173                ByteBuffer status = ByteBuffer.allocateDirect(4);
174                status.order(ByteOrder.LITTLE_ENDIAN);
175
176                boolean retval = CompressorJNI.getCompressorShortedStickyFault(m_pcm, status.asIntBuffer());
177                HALUtil.checkStatus(status.asIntBuffer());
178
179                return retval;
180        }
181        /**
182         * @return true if PCM is in fault state : Compressor output 
183         *                      appears to be shorted.
184         */
185        public boolean getCompressorShortedFault() {
186                ByteBuffer status = ByteBuffer.allocateDirect(4);
187                status.order(ByteOrder.LITTLE_ENDIAN);
188
189                boolean retval = CompressorJNI.getCompressorShortedFault(m_pcm, status.asIntBuffer());
190                HALUtil.checkStatus(status.asIntBuffer());
191
192                return retval;
193        }
194        /**
195         * @return true if PCM sticky fault is set : Compressor does not 
196         *                      appear to be wired, i.e. compressor is
197         *                      not drawing enough current.
198         */
199        public boolean getCompressorNotConnectedStickyFault() {
200                ByteBuffer status = ByteBuffer.allocateDirect(4);
201                status.order(ByteOrder.LITTLE_ENDIAN);
202
203                boolean retval = CompressorJNI.getCompressorNotConnectedStickyFault(m_pcm, status.asIntBuffer());
204                HALUtil.checkStatus(status.asIntBuffer());
205
206                return retval;
207        }
208        /**
209         * @return true if PCM is in fault state : Compressor does not 
210         *                      appear to be wired, i.e. compressor is
211         *                      not drawing enough current.
212         */
213        public boolean getCompressorNotConnectedFault() {
214                ByteBuffer status = ByteBuffer.allocateDirect(4);
215                status.order(ByteOrder.LITTLE_ENDIAN);
216
217                boolean retval = CompressorJNI.getCompressorNotConnectedFault(m_pcm, status.asIntBuffer());
218                HALUtil.checkStatus(status.asIntBuffer());
219
220                return retval;
221        }
222        /**
223         * Clear ALL sticky faults inside PCM that Compressor is wired to.
224         *
225         * If a sticky fault is set, then it will be persistently cleared.  Compressor drive
226         *              maybe momentarily disable while flags are being cleared. Care should be 
227         *              taken to not call this too frequently, otherwise normal compressor 
228         *              functionality may be prevented.
229         *
230         * If no sticky faults are set then this call will have no effect.
231         */
232        public void clearAllPCMStickyFaults() {
233                ByteBuffer status = ByteBuffer.allocateDirect(4);
234                status.order(ByteOrder.LITTLE_ENDIAN);
235
236                CompressorJNI.clearAllPCMStickyFaults(m_pcm, status.asIntBuffer());
237                HALUtil.checkStatus(status.asIntBuffer());
238        }
239        @Override
240        public void startLiveWindowMode() {
241        }
242
243        @Override
244        public void stopLiveWindowMode() {
245        }
246
247        @Override
248        public String getSmartDashboardType() {
249                return "Compressor";
250        }
251
252        private ITable m_table;
253
254        @Override
255        public void initTable(ITable subtable) {
256                m_table = subtable;
257                updateTable();
258        }
259
260        @Override
261        public ITable getTable() {
262                return m_table;
263        }
264
265        @Override
266        public void updateTable() {
267        if (m_table != null) {
268            m_table.putBoolean("Enabled", enabled());
269            m_table.putBoolean("Pressure Switch", getPressureSwitchValue());
270        }
271        }
272}