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 }