blob: beb8688e4f919ce16124434d04d7373b9e97b4d1 [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 "AnalogChannel.h"
8#include "AnalogModule.h"
9#include "NetworkCommunication/UsageReporting.h"
10#include "Resource.h"
11#include "WPIErrors.h"
12#include "LiveWindow/LiveWindow.h"
13
14static Resource *channels = NULL;
15
16const UINT8 AnalogChannel::kAccumulatorModuleNumber;
17const UINT32 AnalogChannel::kAccumulatorNumChannels;
18const UINT32 AnalogChannel::kAccumulatorChannels[] = {1, 2};
19
20/**
21 * Common initialization.
22 */
23void AnalogChannel::InitChannel(UINT8 moduleNumber, UINT32 channel)
24{
25 char buf[64];
26 Resource::CreateResourceObject(&channels, kAnalogModules * kAnalogChannels);
27 if (!CheckAnalogModule(moduleNumber))
28 {
29 snprintf(buf, 64, "Analog Module %d", moduleNumber);
30 wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
31 return;
32 }
33 if (!CheckAnalogChannel(channel))
34 {
35 snprintf(buf, 64, "Analog Channel %d", channel);
36 wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
37 return;
38 }
39
40 snprintf(buf, 64, "Analog Input %d (Module: %d)", channel, moduleNumber);
41 if (channels->Allocate((moduleNumber - 1) * kAnalogChannels + channel - 1, buf) == ~0ul)
42 {
43 CloneError(channels);
44 return;
45 }
46 m_channel = channel;
47 m_module = AnalogModule::GetInstance(moduleNumber);
48 if (IsAccumulatorChannel())
49 {
50 tRioStatusCode localStatus = NiFpga_Status_Success;
51 m_accumulator = tAccumulator::create(channel - 1, &localStatus);
52 wpi_setError(localStatus);
53 m_accumulatorOffset=0;
54 }
55 else
56 {
57 m_accumulator = NULL;
58 }
59 LiveWindow::GetInstance()->AddActuator("AnalogChannel",channel, GetModuleNumber(), this);
60 nUsageReporting::report(nUsageReporting::kResourceType_AnalogChannel, channel, GetModuleNumber() - 1);
61}
62
63/**
64 * Construct an analog channel on a specified module.
65 *
66 * @param moduleNumber The analog module (1 or 2).
67 * @param channel The channel number to represent.
68 */
69AnalogChannel::AnalogChannel(UINT8 moduleNumber, UINT32 channel)
70{
71 InitChannel(moduleNumber, channel);
72}
73
74/**
75 * Construct an analog channel on the default module.
76 *
77 * @param channel The channel number to represent.
78 */
79AnalogChannel::AnalogChannel(UINT32 channel)
80{
81 InitChannel(GetDefaultAnalogModule(), channel);
82}
83
84/**
85 * Channel destructor.
86 */
87AnalogChannel::~AnalogChannel()
88{
89 channels->Free((m_module->GetNumber() - 1) * kAnalogChannels + m_channel - 1);
90}
91
92/**
93 * Get the analog module that this channel is on.
94 * @return A pointer to the AnalogModule that this channel is on.
95 */
96AnalogModule *AnalogChannel::GetModule()
97{
98 if (StatusIsFatal()) return NULL;
99 return m_module;
100}
101
102/**
103 * Get a sample straight from this channel on the module.
104 * The sample is a 12-bit value representing the -10V to 10V range of the A/D converter in the module.
105 * The units are in A/D converter codes. Use GetVoltage() to get the analog value in calibrated units.
106 * @return A sample straight from this channel on the module.
107 */
108INT16 AnalogChannel::GetValue()
109{
110 if (StatusIsFatal()) return 0;
111 return m_module->GetValue(m_channel);
112}
113
114/**
115 * Get a sample from the output of the oversample and average engine for this channel.
116 * The sample is 12-bit + the value configured in SetOversampleBits().
117 * The value configured in SetAverageBits() will cause this value to be averaged 2**bits number of samples.
118 * This is not a sliding window. The sample will not change until 2**(OversamplBits + AverageBits) samples
119 * have been acquired from the module on this channel.
120 * Use GetAverageVoltage() to get the analog value in calibrated units.
121 * @return A sample from the oversample and average engine for this channel.
122 */
123INT32 AnalogChannel::GetAverageValue()
124{
125 if (StatusIsFatal()) return 0;
126 return m_module->GetAverageValue(m_channel);
127}
128
129/**
130 * Get a scaled sample straight from this channel on the module.
131 * The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
132 * @return A scaled sample straight from this channel on the module.
133 */
134float AnalogChannel::GetVoltage()
135{
136 if (StatusIsFatal()) return 0.0f;
137 return m_module->GetVoltage(m_channel);
138}
139
140/**
141 * Get a scaled sample from the output of the oversample and average engine for this channel.
142 * The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
143 * Using oversampling will cause this value to be higher resolution, but it will update more slowly.
144 * Using averaging will cause this value to be more stable, but it will update more slowly.
145 * @return A scaled sample from the output of the oversample and average engine for this channel.
146 */
147float AnalogChannel::GetAverageVoltage()
148{
149 if (StatusIsFatal()) return 0.0f;
150 return m_module->GetAverageVoltage(m_channel);
151}
152
153/**
154 * Get the factory scaling least significant bit weight constant.
155 * The least significant bit weight constant for the channel that was calibrated in
156 * manufacturing and stored in an eeprom in the module.
157 *
158 * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
159 *
160 * @return Least significant bit weight.
161 */
162UINT32 AnalogChannel::GetLSBWeight()
163{
164 if (StatusIsFatal()) return 0;
165 return m_module->GetLSBWeight(m_channel);
166}
167
168/**
169 * Get the factory scaling offset constant.
170 * The offset constant for the channel that was calibrated in manufacturing and stored
171 * in an eeprom in the module.
172 *
173 * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
174 *
175 * @return Offset constant.
176 */
177INT32 AnalogChannel::GetOffset()
178{
179 if (StatusIsFatal()) return 0;
180 return m_module->GetOffset(m_channel);
181}
182
183/**
184 * Get the channel number.
185 * @return The channel number.
186 */
187UINT32 AnalogChannel::GetChannel()
188{
189 if (StatusIsFatal()) return 0;
190 return m_channel;
191}
192
193/**
194 * Get the module number.
195 * @return The module number.
196 */
197UINT8 AnalogChannel::GetModuleNumber()
198{
199 if (StatusIsFatal()) return 0;
200 return m_module->GetNumber();
201}
202
203/**
204 * Set the number of averaging bits.
205 * This sets the number of averaging bits. The actual number of averaged samples is 2**bits.
206 * Use averaging to improve the stability of your measurement at the expense of sampling rate.
207 * The averaging is done automatically in the FPGA.
208 *
209 * @param bits Number of bits of averaging.
210 */
211void AnalogChannel::SetAverageBits(UINT32 bits)
212{
213 if (StatusIsFatal()) return;
214 m_module->SetAverageBits(m_channel, bits);
215}
216
217/**
218 * Get the number of averaging bits previously configured.
219 * This gets the number of averaging bits from the FPGA. The actual number of averaged samples is 2**bits.
220 * The averaging is done automatically in the FPGA.
221 *
222 * @return Number of bits of averaging previously configured.
223 */
224UINT32 AnalogChannel::GetAverageBits()
225{
226 if (StatusIsFatal()) return 0;
227 return m_module->GetAverageBits(m_channel);
228}
229
230/**
231 * Set the number of oversample bits.
232 * This sets the number of oversample bits. The actual number of oversampled values is 2**bits.
233 * Use oversampling to improve the resolution of your measurements at the expense of sampling rate.
234 * The oversampling is done automatically in the FPGA.
235 *
236 * @param bits Number of bits of oversampling.
237 */
238void AnalogChannel::SetOversampleBits(UINT32 bits)
239{
240 if (StatusIsFatal()) return;
241 m_module->SetOversampleBits(m_channel, bits);
242}
243
244/**
245 * Get the number of oversample bits previously configured.
246 * This gets the number of oversample bits from the FPGA. The actual number of oversampled values is
247 * 2**bits. The oversampling is done automatically in the FPGA.
248 *
249 * @return Number of bits of oversampling previously configured.
250 */
251UINT32 AnalogChannel::GetOversampleBits()
252{
253 if (StatusIsFatal()) return 0;
254 return m_module->GetOversampleBits(m_channel);
255}
256
257/**
258 * Is the channel attached to an accumulator.
259 *
260 * @return The analog channel is attached to an accumulator.
261 */
262bool AnalogChannel::IsAccumulatorChannel()
263{
264 if (StatusIsFatal()) return false;
265 if(m_module->GetNumber() != kAccumulatorModuleNumber) return false;
266 for (UINT32 i=0; i<kAccumulatorNumChannels; i++)
267 {
268 if (m_channel == kAccumulatorChannels[i]) return true;
269 }
270 return false;
271}
272
273/**
274 * Initialize the accumulator.
275 */
276void AnalogChannel::InitAccumulator()
277{
278 if (StatusIsFatal()) return;
279 m_accumulatorOffset = 0;
280 SetAccumulatorCenter(0);
281 ResetAccumulator();
282}
283
284
285/**
286 * Set an inital value for the accumulator.
287 *
288 * This will be added to all values returned to the user.
289 * @param initialValue The value that the accumulator should start from when reset.
290 */
291void AnalogChannel::SetAccumulatorInitialValue(INT64 initialValue)
292{
293 if (StatusIsFatal()) return;
294 m_accumulatorOffset = initialValue;
295}
296
297/**
298 * Resets the accumulator to the initial value.
299 */
300void AnalogChannel::ResetAccumulator()
301{
302 if (StatusIsFatal()) return;
303 if (m_accumulator == NULL)
304 {
305 wpi_setWPIError(NullParameter);
306 return;
307 }
308 tRioStatusCode localStatus = NiFpga_Status_Success;
309 m_accumulator->strobeReset(&localStatus);
310 wpi_setError(localStatus);
311}
312
313/**
314 * Set the center value of the accumulator.
315 *
316 * The center value is subtracted from each A/D value before it is added to the accumulator. This
317 * is used for the center value of devices like gyros and accelerometers to make integration work
318 * and to take the device offset into account when integrating.
319 *
320 * This center value is based on the output of the oversampled and averaged source from channel 1.
321 * Because of this, any non-zero oversample bits will affect the size of the value for this field.
322 */
323void AnalogChannel::SetAccumulatorCenter(INT32 center)
324{
325 if (StatusIsFatal()) return;
326 if (m_accumulator == NULL)
327 {
328 wpi_setWPIError(NullParameter);
329 return;
330 }
331 tRioStatusCode localStatus = NiFpga_Status_Success;
332 m_accumulator->writeCenter(center, &localStatus);
333 wpi_setError(localStatus);
334}
335
336/**
337 * Set the accumulator's deadband.
338 */
339void AnalogChannel::SetAccumulatorDeadband(INT32 deadband)
340{
341 if (StatusIsFatal()) return;
342 if (m_accumulator == NULL)
343 {
344 wpi_setWPIError(NullParameter);
345 return;
346 }
347 tRioStatusCode localStatus = NiFpga_Status_Success;
348 m_accumulator->writeDeadband(deadband, &localStatus);
349 wpi_setError(localStatus);
350}
351
352/**
353 * Read the accumulated value.
354 *
355 * Read the value that has been accumulating on channel 1.
356 * The accumulator is attached after the oversample and average engine.
357 *
358 * @return The 64-bit value accumulated since the last Reset().
359 */
360INT64 AnalogChannel::GetAccumulatorValue()
361{
362 if (StatusIsFatal()) return 0;
363 if (m_accumulator == NULL)
364 {
365 wpi_setWPIError(NullParameter);
366 return 0;
367 }
368 tRioStatusCode localStatus = NiFpga_Status_Success;
369 INT64 value = m_accumulator->readOutput_Value(&localStatus) + m_accumulatorOffset;
370 wpi_setError(localStatus);
371 return value;
372}
373
374/**
375 * Read the number of accumulated values.
376 *
377 * Read the count of the accumulated values since the accumulator was last Reset().
378 *
379 * @return The number of times samples from the channel were accumulated.
380 */
381UINT32 AnalogChannel::GetAccumulatorCount()
382{
383 if (StatusIsFatal()) return 0;
384 if (m_accumulator == NULL)
385 {
386 wpi_setWPIError(NullParameter);
387 return 0;
388 }
389 tRioStatusCode localStatus = NiFpga_Status_Success;
390 UINT32 count = m_accumulator->readOutput_Count(&localStatus);
391 wpi_setError(localStatus);
392 return count;
393}
394
395
396/**
397 * Read the accumulated value and the number of accumulated values atomically.
398 *
399 * This function reads the value and count from the FPGA atomically.
400 * This can be used for averaging.
401 *
402 * @param value Pointer to the 64-bit accumulated output.
403 * @param count Pointer to the number of accumulation cycles.
404 */
405void AnalogChannel::GetAccumulatorOutput(INT64 *value, UINT32 *count)
406{
407 if (StatusIsFatal()) return;
408 if (m_accumulator == NULL)
409 {
410 wpi_setWPIError(NullParameter);
411 return;
412 }
413 if (value == NULL || count == NULL)
414 {
415 wpi_setWPIError(NullParameter);
416 return;
417 }
418
419 tRioStatusCode localStatus = NiFpga_Status_Success;
420 tAccumulator::tOutput output = m_accumulator->readOutput(&localStatus);
421 *value = output.Value + m_accumulatorOffset;
422 *count = output.Count;
423 wpi_setError(localStatus);
424}
425
426/**
427 * Get the Average voltage for the PID Source base object.
428 *
429 * @return The average voltage.
430 */
431double AnalogChannel::PIDGet()
432{
433 if (StatusIsFatal()) return 0.0;
434 return GetAverageValue();
435}
436
437void AnalogChannel::UpdateTable() {
438 if (m_table != NULL) {
439 m_table->PutNumber("Value", GetAverageVoltage());
440 }
441}
442
443void AnalogChannel::StartLiveWindowMode() {
444
445}
446
447void AnalogChannel::StopLiveWindowMode() {
448
449}
450
451std::string AnalogChannel::GetSmartDashboardType() {
452 return "Analog Input";
453}
454
455void AnalogChannel::InitTable(ITable *subTable) {
456 m_table = subTable;
457 UpdateTable();
458}
459
460ITable * AnalogChannel::GetTable() {
461 return m_table;
462}
463
464