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 }