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 java.nio.ByteBuffer;
011import java.nio.ByteOrder;
012
013import edu.wpi.first.wpilibj.AnalogTriggerOutput.AnalogTriggerType;
014import edu.wpi.first.wpilibj.hal.AnalogJNI;
015import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
016import edu.wpi.first.wpilibj.hal.HAL;
017import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
018import edu.wpi.first.wpilibj.util.BoundaryException;
019
020/**
021 * Class for creating and configuring Analog Triggers.
022 */
023public class AnalogTrigger extends SensorBase implements Sendable {
024  /**
025   * Exceptions dealing with improper operation of the Analog trigger.
026   */
027  public class AnalogTriggerException extends RuntimeException {
028    /**
029     * Create a new exception with the given message.
030     *
031     * @param message the message to pass with the exception
032     */
033    public AnalogTriggerException(String message) {
034      super(message);
035    }
036
037  }
038
039  /**
040   * Where the analog trigger is attached.
041   */
042  protected int m_port;
043  protected int m_index;
044  protected AnalogInput m_analogInput = null;
045  protected boolean m_ownsAnalog = false;
046
047  /**
048   * Constructor for an analog trigger given a channel number.
049   *
050   * @param channel the port to use for the analog trigger
051   */
052  public AnalogTrigger(final int channel) {
053    this(new AnalogInput(channel));
054    m_ownsAnalog = true;
055    addChild(m_analogInput);
056  }
057
058  /**
059   * Construct an analog trigger given an analog channel. This should be used in the case of sharing
060   * an analog channel between the trigger and an analog input object.
061   *
062   * @param channel the AnalogInput to use for the analog trigger
063   */
064  public AnalogTrigger(AnalogInput channel) {
065    m_analogInput = channel;
066    ByteBuffer index = ByteBuffer.allocateDirect(4);
067    index.order(ByteOrder.LITTLE_ENDIAN);
068
069    m_port =
070        AnalogJNI.initializeAnalogTrigger(channel.m_port, index.asIntBuffer());
071    m_index = index.asIntBuffer().get(0);
072
073    HAL.report(tResourceType.kResourceType_AnalogTrigger, channel.getChannel());
074    setName("AnalogTrigger", channel.getChannel());
075  }
076
077  /**
078   * Release the resources used by this object.
079   */
080  @Override
081  public void free() {
082    super.free();
083    AnalogJNI.cleanAnalogTrigger(m_port);
084    m_port = 0;
085    if (m_ownsAnalog && m_analogInput != null) {
086      m_analogInput.free();
087    }
088  }
089
090  /**
091   * Set the upper and lower limits of the analog trigger. The limits are given in ADC codes. If
092   * oversampling is used, the units must be scaled appropriately.
093   *
094   * @param lower the lower raw limit
095   * @param upper the upper raw limit
096   */
097  public void setLimitsRaw(final int lower, final int upper) {
098    if (lower > upper) {
099      throw new BoundaryException("Lower bound is greater than upper");
100    }
101    AnalogJNI.setAnalogTriggerLimitsRaw(m_port, lower, upper);
102  }
103
104  /**
105   * Set the upper and lower limits of the analog trigger. The limits are given as floating point
106   * voltage values.
107   *
108   * @param lower the lower voltage limit
109   * @param upper the upper voltage limit
110   */
111  public void setLimitsVoltage(double lower, double upper) {
112    if (lower > upper) {
113      throw new BoundaryException("Lower bound is greater than upper bound");
114    }
115    AnalogJNI.setAnalogTriggerLimitsVoltage(m_port, lower, upper);
116  }
117
118  /**
119   * Configure the analog trigger to use the averaged vs. raw values. If the value is true, then the
120   * averaged value is selected for the analog trigger, otherwise the immediate value is used.
121   *
122   * @param useAveragedValue true to use an averaged value, false otherwise
123   */
124  public void setAveraged(boolean useAveragedValue) {
125    AnalogJNI.setAnalogTriggerAveraged(m_port, useAveragedValue);
126  }
127
128  /**
129   * Configure the analog trigger to use a filtered value. The analog trigger will operate with a 3
130   * point average rejection filter. This is designed to help with 360 degree pot applications for
131   * the period where the pot crosses through zero.
132   *
133   * @param useFilteredValue true to use a filtered value, false otherwise
134   */
135  public void setFiltered(boolean useFilteredValue) {
136    AnalogJNI.setAnalogTriggerFiltered(m_port, useFilteredValue);
137  }
138
139  /**
140   * Return the index of the analog trigger. This is the FPGA index of this analog trigger
141   * instance.
142   *
143   * @return The index of the analog trigger.
144   */
145  public int getIndex() {
146    return m_index;
147  }
148
149  /**
150   * Return the InWindow output of the analog trigger. True if the analog input is between the upper
151   * and lower limits.
152   *
153   * @return The InWindow output of the analog trigger.
154   */
155  public boolean getInWindow() {
156    return AnalogJNI.getAnalogTriggerInWindow(m_port);
157  }
158
159  /**
160   * Return the TriggerState output of the analog trigger. True if above upper limit. False if below
161   * lower limit. If in Hysteresis, maintain previous state.
162   *
163   * @return The TriggerState output of the analog trigger.
164   */
165  public boolean getTriggerState() {
166    return AnalogJNI.getAnalogTriggerTriggerState(m_port);
167  }
168
169  /**
170   * Creates an AnalogTriggerOutput object. Gets an output object that can be used for routing.
171   * Caller is responsible for deleting the AnalogTriggerOutput object.
172   *
173   * @param type An enum of the type of output object to create.
174   * @return A pointer to a new AnalogTriggerOutput object.
175   */
176  public AnalogTriggerOutput createOutput(AnalogTriggerType type) {
177    return new AnalogTriggerOutput(this, type);
178  }
179
180  @Override
181  public void initSendable(SendableBuilder builder) {
182    if (m_ownsAnalog) {
183      m_analogInput.initSendable(builder);
184    }
185  }
186}