blob: a3420d5057f3a7f895935f3dcc026aebf49b3c0a [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 "AnalogTrigger.h"
8
9#include "AnalogChannel.h"
10#include "AnalogModule.h"
11#include "NetworkCommunication/UsageReporting.h"
12#include "Resource.h"
13#include "WPIErrors.h"
14
15static Resource *triggers = NULL;
16
17/**
18 * Initialize an analog trigger from a slot and channel.
19 * This is the common code for the two constructors that use a slot and channel.
20 */
21void AnalogTrigger::InitTrigger(UINT8 moduleNumber, UINT32 channel)
22{
23 Resource::CreateResourceObject(&triggers, tAnalogTrigger::kNumSystems);
24 UINT32 index = triggers->Allocate("Analog Trigger");
25 if (index == ~0ul)
26 {
27 CloneError(triggers);
28 return;
29 }
30 m_index = (UINT8)index;
31 m_channel = channel;
32 m_analogModule = AnalogModule::GetInstance(moduleNumber);
33
34 tRioStatusCode localStatus = NiFpga_Status_Success;
35 m_trigger = tAnalogTrigger::create(m_index, &localStatus);
36 m_trigger->writeSourceSelect_Channel(m_channel - 1, &localStatus);
37 m_trigger->writeSourceSelect_Module(moduleNumber - 1, &localStatus);
38 wpi_setError(localStatus);
39
40 nUsageReporting::report(nUsageReporting::kResourceType_AnalogTrigger, m_channel, moduleNumber - 1);
41}
42
43/**
44 * Constructor for an analog trigger given a channel number.
45 * The default module is used in this case.
46 *
47 * @param channel The analog channel (1..8).
48 */
49AnalogTrigger::AnalogTrigger(UINT32 channel)
50{
51 InitTrigger(GetDefaultAnalogModule(), channel);
52}
53
54/**
55 * Constructor for an analog trigger given both the slot and channel.
56 *
57 * @param moduleNumber The analog module (1 or 2).
58 * @param channel The analog channel (1..8).
59 */
60AnalogTrigger::AnalogTrigger(UINT8 moduleNumber, UINT32 channel)
61{
62 InitTrigger(moduleNumber, channel);
63}
64
65/**
66 * Construct an analog trigger given an analog channel.
67 * This should be used in the case of sharing an analog channel between the trigger
68 * and an analog input object.
69 */
70AnalogTrigger::AnalogTrigger(AnalogChannel *channel)
71{
72 InitTrigger(channel->GetModuleNumber(), channel->GetChannel());
73}
74
75AnalogTrigger::~AnalogTrigger()
76{
77 triggers->Free(m_index);
78 delete m_trigger;
79}
80
81/**
82 * Set the upper and lower limits of the analog trigger.
83 * The limits are given in ADC codes. If oversampling is used, the units must be scaled
84 * appropriately.
85 */
86void AnalogTrigger::SetLimitsRaw(INT32 lower, INT32 upper)
87{
88 if (StatusIsFatal()) return;
89 if (lower > upper)
90 {
91 wpi_setWPIError(AnalogTriggerLimitOrderError);
92 }
93 tRioStatusCode localStatus = NiFpga_Status_Success;
94 m_trigger->writeLowerLimit(lower, &localStatus);
95 m_trigger->writeUpperLimit(upper, &localStatus);
96 wpi_setError(localStatus);
97}
98
99/**
100 * Set the upper and lower limits of the analog trigger.
101 * The limits are given as floating point voltage values.
102 */
103void AnalogTrigger::SetLimitsVoltage(float lower, float upper)
104{
105 if (StatusIsFatal()) return;
106 if (lower > upper)
107 {
108 wpi_setWPIError(AnalogTriggerLimitOrderError);
109 }
110 // TODO: This depends on the averaged setting. Only raw values will work as is.
111 tRioStatusCode localStatus = NiFpga_Status_Success;
112 m_trigger->writeLowerLimit(m_analogModule->VoltsToValue(m_channel, lower), &localStatus);
113 m_trigger->writeUpperLimit(m_analogModule->VoltsToValue(m_channel, upper), &localStatus);
114 wpi_setError(localStatus);
115}
116
117/**
118 * Configure the analog trigger to use the averaged vs. raw values.
119 * If the value is true, then the averaged value is selected for the analog trigger, otherwise
120 * the immediate value is used.
121 */
122void AnalogTrigger::SetAveraged(bool useAveragedValue)
123{
124 if (StatusIsFatal()) return;
125 tRioStatusCode localStatus = NiFpga_Status_Success;
126 if (m_trigger->readSourceSelect_Filter(&localStatus) != 0)
127 wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not support average and filtering at the same time.");
128 m_trigger->writeSourceSelect_Averaged(useAveragedValue, &localStatus);
129 wpi_setError(localStatus);
130}
131
132/**
133 * Configure the analog trigger to use a filtered value.
134 * The analog trigger will operate with a 3 point average rejection filter. This is designed to
135 * help with 360 degree pot applications for the period where the pot crosses through zero.
136 */
137void AnalogTrigger::SetFiltered(bool useFilteredValue)
138{
139 if (StatusIsFatal()) return;
140 tRioStatusCode localStatus = NiFpga_Status_Success;
141 if (m_trigger->readSourceSelect_Averaged(&localStatus) != 0)
142 wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not support average and filtering at the same time.");
143 m_trigger->writeSourceSelect_Filter(useFilteredValue, &localStatus);
144 wpi_setError(localStatus);
145}
146
147/**
148 * Return the index of the analog trigger.
149 * This is the FPGA index of this analog trigger instance.
150 * @return The index of the analog trigger.
151 */
152UINT32 AnalogTrigger::GetIndex()
153{
154 if (StatusIsFatal()) return ~0ul;
155 return m_index;
156}
157
158/**
159 * Return the InWindow output of the analog trigger.
160 * True if the analog input is between the upper and lower limits.
161 * @return The InWindow output of the analog trigger.
162 */
163bool AnalogTrigger::GetInWindow()
164{
165 if (StatusIsFatal()) return false;
166 tRioStatusCode localStatus = NiFpga_Status_Success;
167 bool result = m_trigger->readOutput_InHysteresis(m_index, &localStatus) != 0;
168 wpi_setError(localStatus);
169 return result;
170}
171
172/**
173 * Return the TriggerState output of the analog trigger.
174 * True if above upper limit.
175 * False if below lower limit.
176 * If in Hysteresis, maintain previous state.
177 * @return The TriggerState output of the analog trigger.
178 */
179bool AnalogTrigger::GetTriggerState()
180{
181 if (StatusIsFatal()) return false;
182 tRioStatusCode localStatus = NiFpga_Status_Success;
183 bool result = m_trigger->readOutput_OverLimit(m_index, &localStatus) != 0;
184 wpi_setError(localStatus);
185 return result;
186}
187
188/**
189 * Creates an AnalogTriggerOutput object.
190 * Gets an output object that can be used for routing.
191 * Caller is responsible for deleting the AnalogTriggerOutput object.
192 * @param type An enum of the type of output object to create.
193 * @return A pointer to a new AnalogTriggerOutput object.
194 */
195AnalogTriggerOutput *AnalogTrigger::CreateOutput(AnalogTriggerOutput::Type type)
196{
197 if (StatusIsFatal()) return NULL;
198 return new AnalogTriggerOutput(this, type);
199}
200