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.LiveWindowSendable;
012    import edu.wpi.first.wpilibj.parsing.IInputOutput;
013    import edu.wpi.first.wpilibj.tables.ITable;
014    import edu.wpi.first.wpilibj.util.AllocationException;
015    import edu.wpi.first.wpilibj.util.CheckedAllocationException;
016    
017    /**
018     * Class to read a digital input.
019     * This class will read digital inputs and return the current value on the channel. Other devices
020     * such as encoders, gear tooth sensors, etc. that are implemented elsewhere will automatically
021     * allocate digital inputs and outputs as required. This class is only for devices like switches
022     * etc. that aren't implemented anywhere else.
023     */
024    public class DigitalInput extends DigitalSource implements IInputOutput, LiveWindowSendable {
025    
026        private int m_channel;
027        private DigitalModule m_module;
028    
029        /**
030         * Create an instance of a DigitalInput.
031         * Creates a digital input given a digital module number and channel. Common creation routine
032         * for all constructors.
033         */
034        private void initDigitalInput(int moduleNumber, int channel) {
035            checkDigitalChannel(channel);
036            checkDigitalModule(moduleNumber);
037            m_channel = channel;
038            m_module = DigitalModule.getInstance(moduleNumber);
039            m_module.allocateDIO(channel, true);
040            UsageReporting.report(UsageReporting.kResourceType_DigitalInput, channel, moduleNumber-1);
041        }
042    
043        /**
044         * Create an instance of a Digital Input class.
045         * Creates a digital input given a channel and uses the default module.
046         * @param channel the port for the digital input
047         */
048        public DigitalInput(int channel) {
049            initDigitalInput(getDefaultDigitalModule(), channel);
050        }
051    
052        /**
053         * Create an instance of a Digital Input class.
054         * Creates a digital input given an channel and module.
055         * @param moduleNumber The number of the digital module to use for this input 
056         * @param channel the port for the digital input
057         */
058        public DigitalInput(int moduleNumber, int channel) {
059            initDigitalInput(moduleNumber, channel);
060        }
061    
062        public void free() {
063            m_module.freeDIO(m_channel);
064        }
065    
066        /**
067         * Get the value from a digital input channel.
068         * Retrieve the value of a single digital input channel from the FPGA.
069         * @return the stats of the digital input
070         */
071        public boolean get() {
072            boolean state = m_module.getDIO(m_channel);
073            if (state) {
074                return true;
075            } else {
076                return false;
077            }
078        }
079    
080        /**
081         * Get the channel of the digital input
082         * @return The GPIO channel number that this object represents.
083         */
084        public int getChannel() {
085            return m_channel;
086        }
087    
088        public int getChannelForRouting() {
089            return DigitalModule.remapDigitalChannel(getChannel() - 1);
090        }
091    
092        public int getModuleForRouting() {
093            return m_module.getModuleNumber() - 1;
094        }
095    
096        public boolean getAnalogTriggerForRouting() {
097            return false;
098        }
099    
100        /**
101         * Request interrupts asynchronously on this digital input.
102         * @param handler The address of the interrupt handler function of type tInterruptHandler that
103         * will be called whenever there is an interrupt on the digitial input port.
104         * Request interrupts in synchronus mode where the user program interrupt handler will be
105         * called when an interrupt occurs.
106         * The default is interrupt on rising edges only.
107         * @param param argument to pass to the handler
108         */
109        public void requestInterrupts(/*tInterruptHandler*/Object handler, Object param) {
110            //TODO: add interrupt support
111    
112            try {
113                m_interruptIndex = interrupts.allocate();
114            } catch (CheckedAllocationException e) {
115                throw new AllocationException("No interrupts are left to be allocated");
116            }
117            
118            allocateInterrupts(false);
119    
120            m_interrupt.writeConfig_WaitForAck(false);
121            m_interrupt.writeConfig_Source_AnalogTrigger(getAnalogTriggerForRouting());
122            m_interrupt.writeConfig_Source_Channel((byte) getChannelForRouting());
123            m_interrupt.writeConfig_Source_Module((byte) getModuleForRouting());
124            setUpSourceEdge(true, false);
125    
126            //TODO: m_manager.registerHandler(handler, param);
127        }
128    
129        /**
130         * Request interrupts synchronously on this digital input.
131         * Request interrupts in synchronus mode where the user program will have to explicitly
132         * wait for the interrupt to occur.
133         * The default is interrupt on rising edges only.
134         */
135        public void requestInterrupts() {
136            try {
137                m_interruptIndex = interrupts.allocate();
138            } catch (CheckedAllocationException e) {
139                throw new AllocationException("No interrupts are left to be allocated");
140            }
141    
142            allocateInterrupts(true);
143    
144            m_interrupt.writeConfig_Source_AnalogTrigger(getAnalogTriggerForRouting());
145            m_interrupt.writeConfig_Source_Channel((byte) getChannelForRouting());
146            m_interrupt.writeConfig_Source_Module((byte) getModuleForRouting());
147            setUpSourceEdge(true, false);
148        }
149    
150        /**
151         *  Set which edge to trigger interrupts on
152         * @param risingEdge true to interrupt on rising edge
153         * @param fallingEdge true to interrupt on falling edge
154         */
155        public void setUpSourceEdge(boolean risingEdge, boolean fallingEdge) {
156            if (m_interrupt != null) {
157                m_interrupt.writeConfig_RisingEdge(risingEdge);
158                m_interrupt.writeConfig_FallingEdge(fallingEdge);
159            }
160        }
161    
162        /*
163         * Live Window code, only does anything if live window is activated.
164         */
165        public String getSmartDashboardType(){
166            return "Digital Input";
167        }
168        private ITable m_table;
169        
170        /**
171         * {@inheritDoc}
172         */
173        public void initTable(ITable subtable) {
174            m_table = subtable;
175            updateTable();
176        }
177        
178        /**
179         * {@inheritDoc}
180         */
181        public void updateTable() {
182            if (m_table != null) {
183                m_table.putBoolean("Value", get());
184            }
185        }
186        
187        /**
188         * {@inheritDoc}
189         */
190        public ITable getTable(){
191            return m_table;
192        }
193        
194        /**
195         * {@inheritDoc}
196         */
197        public void startLiveWindowMode() {}
198        
199        /**
200         * {@inheritDoc}
201         */
202        public void stopLiveWindowMode() {}
203    }