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