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
008package edu.wpi.first.wpilibj;
009
010import java.nio.IntBuffer;
011import java.nio.ByteBuffer;
012
013import edu.wpi.first.wpilibj.hal.HALUtil;
014import edu.wpi.first.wpilibj.hal.SolenoidJNI;
015
016/**
017 * SolenoidBase class is the common base class for the Solenoid and
018 * DoubleSolenoid classes.
019 */
020public abstract class SolenoidBase extends SensorBase {
021
022    private ByteBuffer[] m_ports;
023    protected int m_moduleNumber; ///< The number of the solenoid module being used.
024    protected Resource m_allocated = new Resource(63* SensorBase.kSolenoidChannels);
025
026    /**
027     * Constructor.
028     *
029     * @param moduleNumber The PCM CAN ID
030     */
031    public SolenoidBase(final int moduleNumber) {
032        m_moduleNumber = moduleNumber;
033        m_ports = new ByteBuffer[SensorBase.kSolenoidChannels];
034        for (int i = 0; i < SensorBase.kSolenoidChannels; i++) {
035            ByteBuffer port = SolenoidJNI.getPortWithModule((byte) moduleNumber, (byte) i);
036            IntBuffer status = IntBuffer.allocate(1);
037            m_ports[i] = SolenoidJNI.initializeSolenoidPort(port, status);
038            HALUtil.checkStatus(status);
039        }
040    }
041
042    /**
043     * Set the value of a solenoid.
044     *
045     * @param value The value you want to set on the module.
046     * @param mask The channels you want to be affected.
047     */
048    protected synchronized void set(int value, int mask) {
049        IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
050        for (int i = 0; i < SensorBase.kSolenoidChannels; i++) {
051            int local_mask = 1 << i;
052            if ((mask & local_mask) != 0)
053                SolenoidJNI.setSolenoid(m_ports[i], (byte) (value & local_mask), status);
054        }
055        HALUtil.checkStatus(status);
056    }
057
058    /**
059     * Read all 8 solenoids from the module used by this solenoid as a single byte
060     *
061     * @return The current value of all 8 solenoids on this module.
062     */
063    public byte getAll() {
064        byte value = 0;
065        IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
066        for (int i = 0; i < SensorBase.kSolenoidChannels; i++) {
067            value |= SolenoidJNI.getSolenoid(m_ports[i], status) << i;
068        }
069        HALUtil.checkStatus(status);
070        return value;
071    }
072        /**
073         * Reads complete solenoid blacklist for all 8 solenoids as a single byte.
074         * 
075         *              If a solenoid is shorted, it is added to the blacklist and
076         *              disabled until power cycle, or until faults are cleared.
077         *              @see #clearAllPCMStickyFaults()
078         * 
079         * @return The solenoid blacklist of all 8 solenoids on the module.
080         */
081        public byte getPCMSolenoidBlackList() {
082                IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
083
084                byte retval = SolenoidJNI.getPCMSolenoidBlackList(m_ports[0], status);
085                HALUtil.checkStatus(status);
086
087                return retval;
088        }
089        /**
090         * @return true if PCM sticky fault is set : The common 
091         *                      highside solenoid voltage rail is too low,
092         *                      most likely a solenoid channel is shorted.
093         */
094        public boolean getPCMSolenoidVoltageStickyFault() {
095                IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
096
097                boolean retval = SolenoidJNI.getPCMSolenoidVoltageStickyFault(m_ports[0], status);
098                HALUtil.checkStatus(status);
099
100                return retval;
101        }
102        /**
103         * @return true if PCM is in fault state : The common 
104         *                      highside solenoid voltage rail is too low,
105         *                      most likely a solenoid channel is shorted.
106         */
107        public boolean getPCMSolenoidVoltageFault() {
108                IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
109
110                boolean retval = SolenoidJNI.getPCMSolenoidVoltageFault(m_ports[0], status);
111                HALUtil.checkStatus(status);
112
113                return retval;
114        }
115        /**
116         * Clear ALL sticky faults inside PCM that Compressor is wired to.
117         *
118         * If a sticky fault is set, then it will be persistently cleared.  Compressor drive
119         *              maybe momentarily disable while flags are being cleared. Care should be 
120         *              taken to not call this too frequently, otherwise normal compressor 
121         *              functionality may be prevented.
122         *
123         * If no sticky faults are set then this call will have no effect.
124         */
125        public void clearAllPCMStickyFaults() {
126                IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
127
128                SolenoidJNI.clearAllPCMStickyFaults(m_ports[0], status);
129                HALUtil.checkStatus(status);
130        }
131}