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