1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <stdint.h>
#include <hal/AnalogInput.h>
#include <hal/Types.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
namespace frc {
class DMA;
class DMASample;
/**
* Analog input class.
*
* Connected to each analog channel is an averaging and oversampling engine.
* This engine accumulates the specified ( by SetAverageBits() and
* SetOversampleBits() ) number of samples before returning a new value. This is
* not a sliding window average. The only difference between the oversampled
* samples and the averaged samples is that the oversampled samples are simply
* accumulated effectively increasing the resolution, while the averaged samples
* are divided by the number of samples to retain the resolution, but get more
* stable values.
*/
class AnalogInput : public wpi::Sendable,
public wpi::SendableHelper<AnalogInput> {
friend class AnalogTrigger;
friend class AnalogGyro;
friend class DMA;
friend class DMASample;
public:
static constexpr int kAccumulatorModuleNumber = 1;
static constexpr int kAccumulatorNumChannels = 2;
static constexpr int kAccumulatorChannels[kAccumulatorNumChannels] = {0, 1};
/**
* Construct an analog input.
*
* @param channel The channel number on the roboRIO to represent. 0-3 are
* on-board 4-7 are on the MXP port.
*/
explicit AnalogInput(int channel);
AnalogInput(AnalogInput&&) = default;
AnalogInput& operator=(AnalogInput&&) = default;
~AnalogInput() override = default;
/**
* Get a sample straight from this channel.
*
* The sample is a 12-bit value representing the 0V to 5V range of the A/D
* converter in the module. The units are in A/D converter codes. Use
* GetVoltage() to get the analog value in calibrated units.
*
* @return A sample straight from this channel.
*/
int GetValue() const;
/**
* Get a sample from the output of the oversample and average engine for this
* channel.
*
* The sample is 12-bit + the bits configured in SetOversampleBits().
* The value configured in SetAverageBits() will cause this value to be
* averaged 2**bits number of samples.
*
* This is not a sliding window. The sample will not change until
* 2**(OversampleBits + AverageBits) samples have been acquired from the
* module on this channel.
*
* Use GetAverageVoltage() to get the analog value in calibrated units.
*
* @return A sample from the oversample and average engine for this channel.
*/
int GetAverageValue() const;
/**
* Get a scaled sample straight from this channel.
*
* The value is scaled to units of Volts using the calibrated scaling data
* from GetLSBWeight() and GetOffset().
*
* @return A scaled sample straight from this channel.
*/
double GetVoltage() const;
/**
* Get a scaled sample from the output of the oversample and average engine
* for this channel.
*
* The value is scaled to units of Volts using the calibrated scaling data
* from GetLSBWeight() and GetOffset().
*
* Using oversampling will cause this value to be higher resolution, but it
* will update more slowly.
*
* Using averaging will cause this value to be more stable, but it will update
* more slowly.
*
* @return A scaled sample from the output of the oversample and average
* engine for this channel.
*/
double GetAverageVoltage() const;
/**
* Get the channel number.
*
* @return The channel number.
*/
int GetChannel() const;
/**
* Set the number of averaging bits.
*
* This sets the number of averaging bits. The actual number of averaged
* samples is 2^bits.
*
* Use averaging to improve the stability of your measurement at the expense
* of sampling rate. The averaging is done automatically in the FPGA.
*
* @param bits Number of bits of averaging.
*/
void SetAverageBits(int bits);
/**
* Get the number of averaging bits previously configured.
*
* This gets the number of averaging bits from the FPGA. The actual number of
* averaged samples is 2^bits. The averaging is done automatically in the
* FPGA.
*
* @return Number of bits of averaging previously configured.
*/
int GetAverageBits() const;
/**
* Set the number of oversample bits.
*
* This sets the number of oversample bits. The actual number of oversampled
* values is 2^bits. Use oversampling to improve the resolution of your
* measurements at the expense of sampling rate. The oversampling is done
* automatically in the FPGA.
*
* @param bits Number of bits of oversampling.
*/
void SetOversampleBits(int bits);
/**
* Get the number of oversample bits previously configured.
*
* This gets the number of oversample bits from the FPGA. The actual number of
* oversampled values is 2^bits. The oversampling is done automatically in the
* FPGA.
*
* @return Number of bits of oversampling previously configured.
*/
int GetOversampleBits() const;
/**
* Get the factory scaling least significant bit weight constant.
*
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
*
* @return Least significant bit weight.
*/
int GetLSBWeight() const;
/**
* Get the factory scaling offset constant.
*
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
*
* @return Offset constant.
*/
int GetOffset() const;
/**
* Is the channel attached to an accumulator.
*
* @return The analog input is attached to an accumulator.
*/
bool IsAccumulatorChannel() const;
/**
* Initialize the accumulator.
*/
void InitAccumulator();
/**
* Set an initial value for the accumulator.
*
* This will be added to all values returned to the user.
*
* @param value The value that the accumulator should start from when reset.
*/
void SetAccumulatorInitialValue(int64_t value);
/**
* Resets the accumulator to the initial value.
*/
void ResetAccumulator();
/**
* Set the center value of the accumulator.
*
* The center value is subtracted from each A/D value before it is added to
* the accumulator. This is used for the center value of devices like gyros
* and accelerometers to take the device offset into account when integrating.
*
* This center value is based on the output of the oversampled and averaged
* source from the accumulator channel. Because of this, any non-zero
* oversample bits will affect the size of the value for this field.
*/
void SetAccumulatorCenter(int center);
/**
* Set the accumulator's deadband.
*/
void SetAccumulatorDeadband(int deadband);
/**
* Read the accumulated value.
*
* Read the value that has been accumulating.
* The accumulator is attached after the oversample and average engine.
*
* @return The 64-bit value accumulated since the last Reset().
*/
int64_t GetAccumulatorValue() const;
/**
* Read the number of accumulated values.
*
* Read the count of the accumulated values since the accumulator was last
* Reset().
*
* @return The number of times samples from the channel were accumulated.
*/
int64_t GetAccumulatorCount() const;
/**
* Read the accumulated value and the number of accumulated values atomically.
*
* This function reads the value and count from the FPGA atomically.
* This can be used for averaging.
*
* @param value Reference to the 64-bit accumulated output.
* @param count Reference to the number of accumulation cycles.
*/
void GetAccumulatorOutput(int64_t& value, int64_t& count) const;
/**
* Set the sample rate per channel for all analog channels.
*
* The maximum rate is 500kS/s divided by the number of channels in use.
* This is 62500 samples/s per channel.
*
* @param samplesPerSecond The number of samples per second.
*/
static void SetSampleRate(double samplesPerSecond);
/**
* Get the current sample rate for all channels
*
* @return Sample rate.
*/
static double GetSampleRate();
/**
* Indicates this input is used by a simulated device.
*
* @param device simulated device handle
*/
void SetSimDevice(HAL_SimDeviceHandle device);
void InitSendable(wpi::SendableBuilder& builder) override;
private:
int m_channel;
hal::Handle<HAL_AnalogInputHandle, HAL_FreeAnalogInputPort> m_port;
int64_t m_accumulatorOffset;
};
} // namespace frc