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