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