blob: b5c55661bcf1109ae10a67dc742e6e0fe5fbce03 [file] [log] [blame]
jerrymf1579332013-02-07 01:56:28 +00001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5/*----------------------------------------------------------------------------*/
6
7#include "DigitalInput.h"
8#include "DigitalModule.h"
9#include "NetworkCommunication/UsageReporting.h"
10#include "Resource.h"
11#include "WPIErrors.h"
12
13// TODO: This is not a good place for this...
14Resource *interruptsResource = NULL;
15
16/**
17 * Create an instance of a DigitalInput.
18 * Creates a digital input given a slot and channel. Common creation routine
19 * for all constructors.
20 */
21void DigitalInput::InitDigitalInput(UINT8 moduleNumber, UINT32 channel)
22{
23 char buf[64];
24 Resource::CreateResourceObject(&interruptsResource, tInterrupt::kNumSystems);
25 if (!CheckDigitalModule(moduleNumber))
26 {
27 snprintf(buf, 64, "Digital Module %d", moduleNumber);
28 wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
29 return;
30 }
31 if (!CheckDigitalChannel(channel))
32 {
33 snprintf(buf, 64, "Digital Channel %d", channel);
34 wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
35 return;
36 }
37 m_channel = channel;
38 m_module = DigitalModule::GetInstance(moduleNumber);
39 m_module->AllocateDIO(channel, true);
40
41 nUsageReporting::report(nUsageReporting::kResourceType_DigitalInput, channel, moduleNumber - 1);
42}
43
44/**
45 * Create an instance of a Digital Input class.
46 * Creates a digital input given a channel and uses the default module.
47 *
48 * @param channel The digital channel (1..14).
49 */
50DigitalInput::DigitalInput(UINT32 channel)
51{
52 InitDigitalInput(GetDefaultDigitalModule(), channel);
53}
54
55/**
56 * Create an instance of a Digital Input class.
57 * Creates a digital input given an channel and module.
58 *
59 * @param moduleNumber The digital module (1 or 2).
60 * @param channel The digital channel (1..14).
61 */
62DigitalInput::DigitalInput(UINT8 moduleNumber, UINT32 channel)
63{
64 InitDigitalInput(moduleNumber, channel);
65}
66
67/**
68 * Free resources associated with the Digital Input class.
69 */
70DigitalInput::~DigitalInput()
71{
72 if (StatusIsFatal()) return;
73 if (m_manager != NULL)
74 {
75 delete m_manager;
76 delete m_interrupt;
77 interruptsResource->Free(m_interruptIndex);
78 }
79 m_module->FreeDIO(m_channel);
80}
81
82/*
83 * Get the value from a digital input channel.
84 * Retrieve the value of a single digital input channel from the FPGA.
85 */
86UINT32 DigitalInput::Get()
87{
88 if (StatusIsFatal()) return 0;
89 return m_module->GetDIO(m_channel);
90}
91
92/**
93 * @return The GPIO channel number that this object represents.
94 */
95UINT32 DigitalInput::GetChannel()
96{
97 return m_channel;
98}
99
100/**
101 * @return The value to be written to the channel field of a routing mux.
102 */
103UINT32 DigitalInput::GetChannelForRouting()
104{
105 return DigitalModule::RemapDigitalChannel(GetChannel() - 1);
106}
107
108/**
109 * @return The value to be written to the module field of a routing mux.
110 */
111UINT32 DigitalInput::GetModuleForRouting()
112{
113 if (StatusIsFatal()) return 0;
114 return m_module->GetNumber() - 1;
115}
116
117/**
118 * @return The value to be written to the analog trigger field of a routing mux.
119 */
120bool DigitalInput::GetAnalogTriggerForRouting()
121{
122 return false;
123}
124
125/**
126 * Request interrupts asynchronously on this digital input.
127 * @param handler The address of the interrupt handler function of type tInterruptHandler that
128 * will be called whenever there is an interrupt on the digitial input port.
129 * Request interrupts in synchronus mode where the user program interrupt handler will be
130 * called when an interrupt occurs.
131 * The default is interrupt on rising edges only.
132 */
133void DigitalInput::RequestInterrupts(tInterruptHandler handler, void *param)
134{
135 if (StatusIsFatal()) return;
136 UINT32 index = interruptsResource->Allocate("Async Interrupt");
137 if (index == ~0ul)
138 {
139 CloneError(interruptsResource);
140 return;
141 }
142 m_interruptIndex = index;
143
144 // Creates a manager too
145 AllocateInterrupts(false);
146
147 tRioStatusCode localStatus = NiFpga_Status_Success;
148 m_interrupt->writeConfig_WaitForAck(false, &localStatus);
149 m_interrupt->writeConfig_Source_AnalogTrigger(GetAnalogTriggerForRouting(), &localStatus);
150 m_interrupt->writeConfig_Source_Channel(GetChannelForRouting(), &localStatus);
151 m_interrupt->writeConfig_Source_Module(GetModuleForRouting(), &localStatus);
152 SetUpSourceEdge(true, false);
153
154 m_manager->registerHandler(handler, param, &localStatus);
155 wpi_setError(localStatus);
156}
157
158/**
159 * Request interrupts synchronously on this digital input.
160 * Request interrupts in synchronus mode where the user program will have to explicitly
161 * wait for the interrupt to occur.
162 * The default is interrupt on rising edges only.
163 */
164void DigitalInput::RequestInterrupts()
165{
166 if (StatusIsFatal()) return;
167 UINT32 index = interruptsResource->Allocate("Sync Interrupt");
168 if (index == ~0ul)
169 {
170 CloneError(interruptsResource);
171 return;
172 }
173 m_interruptIndex = index;
174
175 AllocateInterrupts(true);
176
177 tRioStatusCode localStatus = NiFpga_Status_Success;
178 m_interrupt->writeConfig_Source_AnalogTrigger(GetAnalogTriggerForRouting(), &localStatus);
179 m_interrupt->writeConfig_Source_Channel(GetChannelForRouting(), &localStatus);
180 m_interrupt->writeConfig_Source_Module(GetModuleForRouting(), &localStatus);
181 SetUpSourceEdge(true, false);
182 wpi_setError(localStatus);
183}
184
185void DigitalInput::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
186{
187 if (StatusIsFatal()) return;
188 if (m_interrupt == NULL)
189 {
190 wpi_setWPIErrorWithContext(NullParameter, "You must call RequestInterrupts before SetUpSourceEdge");
191 return;
192 }
193 tRioStatusCode localStatus = NiFpga_Status_Success;
194 if (m_interrupt != NULL)
195 {
196 m_interrupt->writeConfig_RisingEdge(risingEdge, &localStatus);
197 m_interrupt->writeConfig_FallingEdge(fallingEdge, &localStatus);
198 }
199 wpi_setError(localStatus);
200}
201
202void DigitalInput::UpdateTable() {
203 if (m_table != NULL) {
204 m_table->PutBoolean("Value", Get());
205 }
206}
207
208void DigitalInput::StartLiveWindowMode() {
209
210}
211
212void DigitalInput::StopLiveWindowMode() {
213
214}
215
216std::string DigitalInput::GetSmartDashboardType() {
217 return "DigitalInput";
218}
219
220void DigitalInput::InitTable(ITable *subTable) {
221 m_table = subTable;
222 UpdateTable();
223}
224
225ITable * DigitalInput::GetTable() {
226 return m_table;
227}