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.communication.FRCNetworkCommunicationsLibrary.tResourceType; 011import edu.wpi.first.wpilibj.communication.UsageReporting; 012import edu.wpi.first.wpilibj.hal.AnalogJNI; 013import edu.wpi.first.wpilibj.hal.HALUtil; 014 015import java.nio.IntBuffer; 016 017/** 018 * Class to represent a specific output from an analog trigger. This class is 019 * used to get the current output value and also as a DigitalSource to provide 020 * routing of an output to digital subsystems on the FPGA such as Counter, 021 * Encoder, and Interrupt. 022 * 023 * The TriggerState output indicates the primary output value of the trigger. If 024 * the analog signal is less than the lower limit, the output is false. If the 025 * analog value is greater than the upper limit, then the output is true. If the 026 * analog value is in between, then the trigger output state maintains its most 027 * recent value. 028 * 029 * The InWindow output indicates whether or not the analog signal is inside the 030 * range defined by the limits. 031 * 032 * The RisingPulse and FallingPulse outputs detect an instantaneous transition 033 * from above the upper limit to below the lower limit, and vise versa. These 034 * pulses represent a rollover condition of a sensor and can be routed to an up 035 * / down couter or to interrupts. Because the outputs generate a pulse, they 036 * cannot be read directly. To help ensure that a rollover condition is not 037 * missed, there is an average rejection filter available that operates on the 038 * upper 8 bits of a 12 bit number and selects the nearest outlyer of 3 samples. 039 * This will reject a sample that is (due to averaging or sampling) errantly 040 * between the two limits. This filter will fail if more than one sample in a 041 * row is errantly in between the two limits. You may see this problem if 042 * attempting to use this feature with a mechanical rollover sensor, such as a 043 * 360 degree no-stop potentiometer without signal conditioning, because the 044 * rollover transition is not sharp / clean enough. Using the averaging engine 045 * may help with this, but rotational speeds of the sensor will then be limited. 046 */ 047public class AnalogTriggerOutput extends DigitalSource { 048 049 /** 050 * Exceptions dealing with improper operation of the Analog trigger output 051 */ 052 public class AnalogTriggerOutputException extends RuntimeException { 053 054 /** 055 * Create a new exception with the given message 056 * 057 * @param message 058 * the message to pass with the exception 059 */ 060 public AnalogTriggerOutputException(String message) { 061 super(message); 062 } 063 064 } 065 066 private final AnalogTrigger m_trigger; 067 private final AnalogTriggerType m_outputType; 068 069 /** 070 * Create an object that represents one of the four outputs from an analog 071 * trigger. 072 * 073 * Because this class derives from DigitalSource, it can be passed into 074 * routing functions for Counter, Encoder, etc. 075 * 076 * @param trigger 077 * The trigger for which this is an output. 078 * @param outputType 079 * An enum that specifies the output on the trigger to represent. 080 */ 081 public AnalogTriggerOutput(AnalogTrigger trigger, final AnalogTriggerType outputType) { 082 if (trigger == null) 083 throw new NullPointerException("Analog Trigger given was null"); 084 if (outputType == null) 085 throw new NullPointerException("Analog Trigger Type given was null"); 086 m_trigger = trigger; 087 m_outputType = outputType; 088 089 UsageReporting.report(tResourceType.kResourceType_AnalogTriggerOutput, 090 trigger.getIndex(), outputType.value); 091 } 092 093 @Override 094 public void free() { 095 096 } 097 098 /** 099 * Get the state of the analog trigger output. 100 * 101 * @return The state of the analog trigger output. 102 */ 103 public boolean get() { 104 IntBuffer status = IntBuffer.allocate(1); 105 byte value = AnalogJNI.getAnalogTriggerOutput(m_trigger.m_port, 106 m_outputType.value, status); 107 HALUtil.checkStatus(status); 108 return value != 0; 109 } 110 111 @Override 112 public int getChannelForRouting() { 113 return (m_trigger.m_index << 2) + m_outputType.value; 114 } 115 116 @Override 117 public byte getModuleForRouting() { 118 return (byte) (m_trigger.m_index >> 2); 119 } 120 121 @Override 122 public boolean getAnalogTriggerForRouting() { 123 return true; 124 } 125 126 /** 127 * Defines the state in which the AnalogTrigger triggers 128 * @author jonathanleitschuh 129 */ 130 public enum AnalogTriggerType{ 131 kInWindow(AnalogJNI.AnalogTriggerType.kInWindow), 132 kState(AnalogJNI.AnalogTriggerType.kState), 133 kRisingPulse(AnalogJNI.AnalogTriggerType.kRisingPulse), 134 kFallingPulse(AnalogJNI.AnalogTriggerType.kFallingPulse); 135 136 private final int value; 137 138 private AnalogTriggerType(int value){ 139 this.value = value; 140 } 141 } 142}