001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.wpilibj;
006
007import edu.wpi.first.hal.AnalogJNI;
008import edu.wpi.first.hal.HAL;
009import edu.wpi.first.hal.SimDevice;
010import edu.wpi.first.util.sendable.Sendable;
011import edu.wpi.first.util.sendable.SendableBuilder;
012import edu.wpi.first.util.sendable.SendableRegistry;
013
014/**
015 * Analog channel class.
016 *
017 * <p>Each analog channel is read from hardware as a 12-bit number representing 0V to 3.3V.
018 *
019 * <p>Connected to each analog channel is an averaging and oversampling engine. This engine
020 * accumulates the specified ( by setAverageBits() and setOversampleBits() ) number of samples
021 * before returning a new value. This is not a sliding window average. The only difference between
022 * the oversampled samples and the averaged samples is that the oversampled samples are simply
023 * accumulated effectively increasing the resolution, while the averaged samples are divided by the
024 * number of samples to retain the resolution, but get more stable values.
025 */
026public class AnalogInput implements Sendable, AutoCloseable {
027  int m_port; // explicit no modifier, private and package accessible.
028  private int m_channel;
029
030  /**
031   * Construct an analog channel.
032   *
033   * @param channel The channel number to represent. 0-3 are on-board 4-7 are on the MXP port.
034   */
035  @SuppressWarnings("this-escape")
036  public AnalogInput(final int channel) {
037    AnalogJNI.checkAnalogInputChannel(channel);
038    m_channel = channel;
039
040    m_port = AnalogJNI.initializeAnalogInputPort(channel);
041
042    HAL.reportUsage("IO", channel, "AnalogInput");
043    SendableRegistry.add(this, "AnalogInput", channel);
044  }
045
046  @Override
047  public void close() {
048    SendableRegistry.remove(this);
049    AnalogJNI.freeAnalogInputPort(m_port);
050    m_port = 0;
051    m_channel = 0;
052  }
053
054  /**
055   * Get a sample straight from this channel. The sample is a 12-bit value representing the 0V to
056   * 3.3V range of the A/D converter. The units are in A/D converter codes. Use GetVoltage() to get
057   * the analog value in calibrated units.
058   *
059   * @return A sample straight from this channel.
060   */
061  public int getValue() {
062    return AnalogJNI.getAnalogValue(m_port);
063  }
064
065  /**
066   * Get a sample from the output of the oversample and average engine for this channel. The sample
067   * is 12-bit + the bits configured in SetOversampleBits(). The value configured in
068   * setAverageBits() will cause this value to be averaged 2^bits number of samples. This is not a
069   * sliding window. The sample will not change until 2^(OversampleBits + AverageBits) samples have
070   * been acquired from this channel. Use getAverageVoltage() to get the analog value in calibrated
071   * units.
072   *
073   * @return A sample from the oversample and average engine for this channel.
074   */
075  public int getAverageValue() {
076    return AnalogJNI.getAnalogAverageValue(m_port);
077  }
078
079  /**
080   * Get a scaled sample straight from this channel. The value is scaled to units of Volts using the
081   * calibrated scaling data from getLSBWeight() and getOffset().
082   *
083   * @return A scaled sample straight from this channel.
084   */
085  public double getVoltage() {
086    return AnalogJNI.getAnalogVoltage(m_port);
087  }
088
089  /**
090   * Get a scaled sample from the output of the oversample and average engine for this channel. The
091   * value is scaled to units of Volts using the calibrated scaling data from getLSBWeight() and
092   * getOffset(). Using oversampling will cause this value to be higher resolution, but it will
093   * update more slowly. Using averaging will cause this value to be more stable, but it will update
094   * more slowly.
095   *
096   * @return A scaled sample from the output of the oversample and average engine for this channel.
097   */
098  public double getAverageVoltage() {
099    return AnalogJNI.getAnalogAverageVoltage(m_port);
100  }
101
102  /**
103   * Get the factory scaling the least significant bit weight constant. The least significant bit
104   * weight constant for the channel that was calibrated in manufacturing and stored in an eeprom.
105   *
106   * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
107   *
108   * @return Least significant bit weight.
109   */
110  public long getLSBWeight() {
111    return AnalogJNI.getAnalogLSBWeight(m_port);
112  }
113
114  /**
115   * Get the factory scaling offset constant. The offset constant for the channel that was
116   * calibrated in manufacturing and stored in an eeprom.
117   *
118   * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
119   *
120   * @return Offset constant.
121   */
122  public int getOffset() {
123    return AnalogJNI.getAnalogOffset(m_port);
124  }
125
126  /**
127   * Get the channel number.
128   *
129   * @return The channel number.
130   */
131  public int getChannel() {
132    return m_channel;
133  }
134
135  /**
136   * Set the number of averaging bits. This sets the number of averaging bits. The actual number of
137   * averaged samples is 2^bits. The averaging is done automatically in the FPGA.
138   *
139   * @param bits The number of averaging bits.
140   */
141  public void setAverageBits(final int bits) {
142    AnalogJNI.setAnalogAverageBits(m_port, bits);
143  }
144
145  /**
146   * Get the number of averaging bits. This gets the number of averaging bits from the FPGA. The
147   * actual number of averaged samples is 2^bits. The averaging is done automatically in the FPGA.
148   *
149   * @return The number of averaging bits.
150   */
151  public int getAverageBits() {
152    return AnalogJNI.getAnalogAverageBits(m_port);
153  }
154
155  /**
156   * Set the number of oversample bits. This sets the number of oversample bits. The actual number
157   * of oversampled values is 2^bits. The oversampling is done automatically in the FPGA.
158   *
159   * @param bits The number of oversample bits.
160   */
161  public void setOversampleBits(final int bits) {
162    AnalogJNI.setAnalogOversampleBits(m_port, bits);
163  }
164
165  /**
166   * Get the number of oversample bits. This gets the number of oversample bits from the FPGA. The
167   * actual number of oversampled values is 2^bits. The oversampling is done automatically in the
168   * FPGA.
169   *
170   * @return The number of oversample bits.
171   */
172  public int getOversampleBits() {
173    return AnalogJNI.getAnalogOversampleBits(m_port);
174  }
175
176  /**
177   * Set the sample rate per channel.
178   *
179   * <p>This is a global setting for all channels. The maximum rate is 500kS/s divided by the number
180   * of channels in use. This is 62500 samples/s per channel if all 8 channels are used.
181   *
182   * @param samplesPerSecond The number of samples per second.
183   */
184  public static void setGlobalSampleRate(final double samplesPerSecond) {
185    AnalogJNI.setAnalogSampleRate(samplesPerSecond);
186  }
187
188  /**
189   * Get the current sample rate.
190   *
191   * <p>This assumes one entry in the scan list. This is a global setting for all channels.
192   *
193   * @return Sample rate.
194   */
195  public static double getGlobalSampleRate() {
196    return AnalogJNI.getAnalogSampleRate();
197  }
198
199  /**
200   * Indicates this input is used by a simulated device.
201   *
202   * @param device simulated device handle
203   */
204  public void setSimDevice(SimDevice device) {
205    AnalogJNI.setAnalogInputSimDevice(m_port, device.getNativeHandle());
206  }
207
208  @Override
209  public void initSendable(SendableBuilder builder) {
210    builder.setSmartDashboardType("Analog Input");
211    builder.addDoubleProperty("Value", this::getAverageVoltage, null);
212  }
213}