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