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