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    
008    package edu.wpi.first.wpilibj;
009    
010    import edu.wpi.first.wpilibj.communication.UsageReporting;
011    import edu.wpi.first.wpilibj.livewindow.LiveWindow;
012    import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
013    import edu.wpi.first.wpilibj.tables.ITable;
014    import edu.wpi.first.wpilibj.tables.ITableListener;
015    import edu.wpi.first.wpilibj.util.AllocationException;
016    import edu.wpi.first.wpilibj.util.CheckedAllocationException;
017    
018    /**
019     * Solenoid class for running high voltage Digital Output (9472 module).
020     *
021     * The Solenoid class is typically used for pneumatics solenoids, but could be used
022     * for any device within the current spec of the 9472 module.
023     */
024    public class Solenoid extends SolenoidBase implements LiveWindowSendable {
025    
026        private int m_channel; ///< The channel on the module to control.
027    
028        /**
029         * Common function to implement constructor behavior.
030         */
031        private synchronized void initSolenoid() {
032            checkSolenoidModule(m_moduleNumber);
033            checkSolenoidChannel(m_channel);
034    
035            try {
036                m_allocated.allocate((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1);
037            } catch (CheckedAllocationException e) {
038                throw new AllocationException(
039                        "Solenoid channel " + m_channel + " on module " + m_moduleNumber + " is already allocated");
040            }
041    
042            LiveWindow.addActuator("Solenoid", m_moduleNumber, m_channel, this);
043            UsageReporting.report(UsageReporting.kResourceType_Solenoid, m_channel, m_moduleNumber - 1);
044        }
045    
046        /**
047         * Constructor.
048         *
049         * @param channel The channel on the module to control.
050         */
051        public Solenoid(final int channel) {
052            super(getDefaultSolenoidModule());
053            m_channel = channel;
054            initSolenoid();
055        }
056    
057        /**
058         * Constructor.
059         *
060         * @param moduleNumber The module number of the solenoid module to use.
061         * @param channel The channel on the module to control.
062         */
063        public Solenoid(final int moduleNumber, final int channel) {
064            super(moduleNumber);
065            m_channel = channel;
066            initSolenoid();
067        }
068    
069        /**
070         * Destructor.
071         */
072        public synchronized void free() {
073            m_allocated.free((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1);
074        }
075    
076        /**
077         * Set the value of a solenoid.
078         *
079         * @param on Turn the solenoid output off or on.
080         */
081        public void set(boolean on) {
082            byte value = (byte)(on ? 0xFF : 0x00);
083            byte mask = (byte)(1 << (m_channel - 1));
084    
085            set(value, mask);
086        }
087    
088        /**
089         * Read the current value of the solenoid.
090         *
091         * @return The current value of the solenoid.
092         */
093        public boolean get() {
094            int value = getAll() & ( 1 << (m_channel - 1));
095            return (value != 0);
096        }
097    
098        /*
099         * Live Window code, only does anything if live window is activated.
100         */
101        public String getSmartDashboardType(){
102            return "Solenoid";
103        }
104        private ITable m_table;
105        private ITableListener m_table_listener;
106        
107        /**
108         * {@inheritDoc}
109         */
110        public void initTable(ITable subtable) {
111            m_table = subtable;
112            updateTable();
113        }
114        
115        /**
116         * {@inheritDoc}
117         */
118        public ITable getTable(){
119            return m_table;
120        }
121        
122        /**
123         * {@inheritDoc}
124         */
125        public void updateTable() {
126            if (m_table != null) {
127                m_table.putBoolean("Value", get());
128            }
129        }
130        
131    
132        /**
133         * {@inheritDoc}
134         */
135        public void startLiveWindowMode() {
136            set(false); // Stop for safety
137            m_table_listener = new ITableListener() {
138                public void valueChanged(ITable itable, String key, Object value, boolean bln) {
139                    set(((Boolean) value).booleanValue());
140                }
141            };
142            m_table.addTableListener("Value", m_table_listener, true);
143        }
144        
145        /**
146         * {@inheritDoc}
147         */
148        public void stopLiveWindowMode() {
149            set(false); // Stop for safety
150            // TODO: Broken, should only remove the listener from "Value" only.
151            m_table.removeTableListener(m_table_listener);
152        }
153    }