001/*----------------------------------------------------------------------------*/
002/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
003/* Open Source Software - may be modified and shared by FRC teams. The code   */
004/* must be accompanied by the FIRST BSD license file in the root directory of */
005/* the project.                                                               */
006/*----------------------------------------------------------------------------*/
007
008package edu.wpi.first.wpilibj;
009
010import edu.wpi.first.wpilibj.hal.AnalogJNI;
011import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
012import edu.wpi.first.wpilibj.hal.HAL;
013import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
014import edu.wpi.first.wpilibj.util.AllocationException;
015
016/**
017 * Analog channel class.
018 *
019 * <p>Each analog channel is read from hardware as a 12-bit number representing 0V to 5V.
020 *
021 * <p>Connected to each analog channel is an averaging and oversampling engine. This engine
022 * accumulates the specified ( by setAverageBits() and setOversampleBits() ) number of samples
023 * before returning a new value. This is not a sliding window average. The only difference between
024 * the oversampled samples and the averaged samples is that the oversampled samples are simply
025 * accumulated effectively increasing the resolution, while the averaged samples are divided by the
026 * number of samples to retain the resolution, but get more stable values.
027 */
028public class AnalogInput extends SensorBase implements PIDSource, Sendable {
029  private static final int kAccumulatorSlot = 1;
030  int m_port; // explicit no modifier, private and package accessible.
031  private int m_channel;
032  private static final int[] kAccumulatorChannels = {0, 1};
033  private long m_accumulatorOffset;
034  protected PIDSourceType m_pidSource = PIDSourceType.kDisplacement;
035
036  /**
037   * Construct an analog channel.
038   *
039   * @param channel The channel number to represent. 0-3 are on-board 4-7 are on the MXP port.
040   */
041  public AnalogInput(final int channel) {
042    checkAnalogInputChannel(channel);
043    m_channel = channel;
044
045    final int portHandle = AnalogJNI.getPort((byte) channel);
046    m_port = AnalogJNI.initializeAnalogInputPort(portHandle);
047
048    HAL.report(tResourceType.kResourceType_AnalogChannel, channel);
049    setName("AnalogInput", channel);
050  }
051
052  /**
053   * Channel destructor.
054   */
055  @Override
056  public void free() {
057    super.free();
058    AnalogJNI.freeAnalogInputPort(m_port);
059    m_port = 0;
060    m_channel = 0;
061    m_accumulatorOffset = 0;
062  }
063
064  /**
065   * Get a sample straight from this channel. The sample is a 12-bit value representing the 0V to 5V
066   * range of the A/D converter. The units are in A/D converter codes. Use GetVoltage() to get the
067   * analog value in calibrated units.
068   *
069   * @return A sample straight from this channel.
070   */
071  public int getValue() {
072    return AnalogJNI.getAnalogValue(m_port);
073  }
074
075  /**
076   * Get a sample from the output of the oversample and average engine for this channel. The sample
077   * is 12-bit + the bits configured in SetOversampleBits(). The value configured in
078   * setAverageBits() will cause this value to be averaged 2^bits number of samples. This is not a
079   * sliding window. The sample will not change until 2^(OversampleBits + AverageBits) samples have
080   * been acquired from this channel. Use getAverageVoltage() to get the analog value in calibrated
081   * units.
082   *
083   * @return A sample from the oversample and average engine for this channel.
084   */
085  public int getAverageValue() {
086    return AnalogJNI.getAnalogAverageValue(m_port);
087  }
088
089  /**
090   * Get a scaled sample straight from this channel. The value is scaled to units of Volts using the
091   * calibrated scaling data from getLSBWeight() and getOffset().
092   *
093   * @return A scaled sample straight from this channel.
094   */
095  public double getVoltage() {
096    return AnalogJNI.getAnalogVoltage(m_port);
097  }
098
099  /**
100   * Get a scaled sample from the output of the oversample and average engine for this channel. The
101   * value is scaled to units of Volts using the calibrated scaling data from getLSBWeight() and
102   * getOffset(). Using oversampling will cause this value to be higher resolution, but it will
103   * update more slowly. Using averaging will cause this value to be more stable, but it will update
104   * more slowly.
105   *
106   * @return A scaled sample from the output of the oversample and average engine for this channel.
107   */
108  public double getAverageVoltage() {
109    return AnalogJNI.getAnalogAverageVoltage(m_port);
110  }
111
112  /**
113   * Get the factory scaling least significant bit weight constant. The least significant bit weight
114   * constant for the channel that was calibrated in manufacturing and stored in an eeprom.
115   *
116   * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
117   *
118   * @return Least significant bit weight.
119   */
120  public long getLSBWeight() {
121    return AnalogJNI.getAnalogLSBWeight(m_port);
122  }
123
124  /**
125   * Get the factory scaling offset constant. The offset constant for the channel that was
126   * calibrated in manufacturing and stored in an eeprom.
127   *
128   * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
129   *
130   * @return Offset constant.
131   */
132  public int getOffset() {
133    return AnalogJNI.getAnalogOffset(m_port);
134  }
135
136  /**
137   * Get the channel number.
138   *
139   * @return The channel number.
140   */
141  public int getChannel() {
142    return m_channel;
143  }
144
145  /**
146   * Set the number of averaging bits. This sets the number of averaging bits. The actual number of
147   * averaged samples is 2^bits. The averaging is done automatically in the FPGA.
148   *
149   * @param bits The number of averaging bits.
150   */
151  public void setAverageBits(final int bits) {
152    AnalogJNI.setAnalogAverageBits(m_port, bits);
153  }
154
155  /**
156   * Get the number of averaging bits. This gets the number of averaging bits from the FPGA. The
157   * actual number of averaged samples is 2^bits. The averaging is done automatically in the FPGA.
158   *
159   * @return The number of averaging bits.
160   */
161  public int getAverageBits() {
162    return AnalogJNI.getAnalogAverageBits(m_port);
163  }
164
165  /**
166   * Set the number of oversample bits. This sets the number of oversample bits. The actual number
167   * of oversampled values is 2^bits. The oversampling is done automatically in the FPGA.
168   *
169   * @param bits The number of oversample bits.
170   */
171  public void setOversampleBits(final int bits) {
172    AnalogJNI.setAnalogOversampleBits(m_port, bits);
173  }
174
175  /**
176   * Get the number of oversample bits. This gets the number of oversample bits from the FPGA. The
177   * actual number of oversampled values is 2^bits. The oversampling is done automatically in the
178   * FPGA.
179   *
180   * @return The number of oversample bits.
181   */
182  public int getOversampleBits() {
183    return AnalogJNI.getAnalogOversampleBits(m_port);
184  }
185
186  /**
187   * Initialize the accumulator.
188   */
189  public void initAccumulator() {
190    if (!isAccumulatorChannel()) {
191      throw new AllocationException("Accumulators are only available on slot " + kAccumulatorSlot
192          + " on channels " + kAccumulatorChannels[0] + ", " + kAccumulatorChannels[1]);
193    }
194    m_accumulatorOffset = 0;
195    AnalogJNI.initAccumulator(m_port);
196  }
197
198  /**
199   * Set an initial value for the accumulator.
200   *
201   * <p>This will be added to all values returned to the user.
202   *
203   * @param initialValue The value that the accumulator should start from when reset.
204   */
205  public void setAccumulatorInitialValue(long initialValue) {
206    m_accumulatorOffset = initialValue;
207  }
208
209  /**
210   * Resets the accumulator to the initial value.
211   */
212  public void resetAccumulator() {
213    AnalogJNI.resetAccumulator(m_port);
214
215    // Wait until the next sample, so the next call to getAccumulator*()
216    // won't have old values.
217    final double sampleTime = 1.0 / getGlobalSampleRate();
218    final double overSamples = 1 << getOversampleBits();
219    final double averageSamples = 1 << getAverageBits();
220    Timer.delay(sampleTime * overSamples * averageSamples);
221
222  }
223
224  /**
225   * Set the center value of the accumulator.
226   *
227   * <p>The center value is subtracted from each A/D value before it is added to the accumulator.
228   * This is used for the center value of devices like gyros and accelerometers to take the device
229   * offset into account when integrating.
230   *
231   * <p>This center value is based on the output of the oversampled and averaged source the
232   * accumulator channel. Because of this, any non-zero oversample bits will affect the size of the
233   * value for this field.
234   */
235  public void setAccumulatorCenter(int center) {
236    AnalogJNI.setAccumulatorCenter(m_port, center);
237  }
238
239  /**
240   * Set the accumulator's deadband.
241   *
242   * @param deadband The deadband size in ADC codes (12-bit value)
243   */
244  public void setAccumulatorDeadband(int deadband) {
245    AnalogJNI.setAccumulatorDeadband(m_port, deadband);
246  }
247
248  /**
249   * Read the accumulated value.
250   *
251   * <p>Read the value that has been accumulating. The accumulator is attached after the oversample
252   * and average engine.
253   *
254   * @return The 64-bit value accumulated since the last Reset().
255   */
256  public long getAccumulatorValue() {
257    return AnalogJNI.getAccumulatorValue(m_port) + m_accumulatorOffset;
258  }
259
260  /**
261   * Read the number of accumulated values.
262   *
263   * <p>Read the count of the accumulated values since the accumulator was last Reset().
264   *
265   * @return The number of times samples from the channel were accumulated.
266   */
267  public long getAccumulatorCount() {
268    return AnalogJNI.getAccumulatorCount(m_port);
269  }
270
271  /**
272   * Read the accumulated value and the number of accumulated values atomically.
273   *
274   * <p>This function reads the value and count from the FPGA atomically. This can be used for
275   * averaging.
276   *
277   * @param result AccumulatorResult object to store the results in.
278   */
279  public void getAccumulatorOutput(AccumulatorResult result) {
280    if (result == null) {
281      throw new IllegalArgumentException("Null parameter `result'");
282    }
283    if (!isAccumulatorChannel()) {
284      throw new IllegalArgumentException(
285          "Channel " + m_channel + " is not an accumulator channel.");
286    }
287    AnalogJNI.getAccumulatorOutput(m_port, result);
288    result.value += m_accumulatorOffset;
289  }
290
291  /**
292   * Is the channel attached to an accumulator.
293   *
294   * @return The analog channel is attached to an accumulator.
295   */
296  public boolean isAccumulatorChannel() {
297    for (int channel : kAccumulatorChannels) {
298      if (m_channel == channel) {
299        return true;
300      }
301    }
302    return false;
303  }
304
305  /**
306   * Set the sample rate per channel.
307   *
308   * <p>This is a global setting for all channels. The maximum rate is 500kS/s divided by the number
309   * of channels in use. This is 62500 samples/s per channel if all 8 channels are used.
310   *
311   * @param samplesPerSecond The number of samples per second.
312   */
313  public static void setGlobalSampleRate(final double samplesPerSecond) {
314    AnalogJNI.setAnalogSampleRate(samplesPerSecond);
315  }
316
317  /**
318   * Get the current sample rate.
319   *
320   * <p>This assumes one entry in the scan list. This is a global setting for all channels.
321   *
322   * @return Sample rate.
323   */
324  public static double getGlobalSampleRate() {
325    return AnalogJNI.getAnalogSampleRate();
326  }
327
328  @Override
329  public void setPIDSourceType(PIDSourceType pidSource) {
330    m_pidSource = pidSource;
331  }
332
333  @Override
334  public PIDSourceType getPIDSourceType() {
335    return m_pidSource;
336  }
337
338  /**
339   * Get the average voltage for use with PIDController.
340   *
341   * @return the average voltage
342   */
343  @Override
344  public double pidGet() {
345    return getAverageVoltage();
346  }
347
348  @Override
349  public void initSendable(SendableBuilder builder) {
350    builder.setSmartDashboardType("Analog Input");
351    builder.addDoubleProperty("Value", this::getAverageVoltage, null);
352  }
353}