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