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