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 008 package edu.wpi.first.wpilibj; 009 010 import edu.wpi.first.wpilibj.communication.UsageReporting; 011 import edu.wpi.first.wpilibj.fpga.tAnalogTrigger; 012 import edu.wpi.first.wpilibj.parsing.IInputOutput; 013 014 /** 015 * Class to represent a specific output from an analog trigger. 016 * This class is used to get the current output value and also as a DigitalSource 017 * to provide routing of an output to digital subsystems on the FPGA such as 018 * Counter, Encoder, and Interrupt. 019 * 020 * The TriggerState output indicates the primary output value of the trigger. If the analog 021 * signal is less than the lower limit, the output is false. If the analog value is greater 022 * than the upper limit, then the output is true. If the analog value is in between, then 023 * the trigger output state maintains its most recent value. 024 * 025 * The InWindow output indicates whether or not the analog signal is inside the range defined 026 * by the limits. 027 * 028 * The RisingPulse and FallingPulse outputs detect an instantaneous transition from above the 029 * upper limit to below the lower limit, and vise versa. These pulses represent a rollover 030 * condition of a sensor and can be routed to an up / down couter or to interrupts. Because 031 * the outputs generate a pulse, they cannot be read directly. To help ensure that a rollover 032 * condition is not missed, there is an average rejection filter available that operates on the 033 * upper 8 bits of a 12 bit number and selects the nearest outlyer of 3 samples. This will reject 034 * a sample that is (due to averaging or sampling) errantly between the two limits. This filter 035 * will fail if more than one sample in a row is errantly in between the two limits. You may see 036 * this problem if attempting to use this feature with a mechanical rollover sensor, such as a 037 * 360 degree no-stop potentiometer without signal conditioning, because the rollover transition 038 * is not sharp / clean enough. Using the averaging engine may help with this, but rotational speeds of 039 * the sensor will then be limited. 040 */ 041 public class AnalogTriggerOutput extends DigitalSource implements IInputOutput{ 042 043 /** 044 * Exceptions dealing with improper operation of the Analog trigger output 045 */ 046 public class AnalogTriggerOutputException extends RuntimeException { 047 048 /** 049 * Create a new exception with the given message 050 * @param message the message to pass with the exception 051 */ 052 public AnalogTriggerOutputException(String message) { 053 super(message); 054 } 055 056 } 057 058 /** 059 * Type determines under what state the analog trigger evaluates to true or 060 * false 061 */ 062 public static class Type { 063 064 /** 065 * The integer value representing this enumeration 066 */ 067 public final int value; 068 static final int kInWindow_val = 0; 069 static final int kTypeState_val = 1; 070 static final int kRisingPulse_val = 2; 071 static final int kFallingPulse_val = 3; 072 /** 073 * outputType: true if in the trigger window 074 */ 075 public static final Type kInWindow = new Type(kInWindow_val); 076 /** 077 * outputType: true if above the upper limit, false if below the lower limit 078 * maintain previous state otherwise 079 */ 080 public static final Type kTypeState = new Type(kTypeState_val); 081 /** 082 * outputType: true on a rising edge 083 */ 084 public static final Type kRisingPulse = new Type(kRisingPulse_val); 085 /** 086 * outputType: true on a falling edge 087 */ 088 public static final Type kFallingPulse = new Type(kFallingPulse_val); 089 090 private Type(int value) { 091 this.value = value; 092 } 093 } 094 private AnalogTrigger m_trigger; 095 private Type m_outputType; 096 097 /** 098 * Create an object that represents one of the four outputs from an analog trigger. 099 * 100 * Because this class derives from DigitalSource, it can be passed into routing functions 101 * for Counter, Encoder, etc. 102 * 103 * @param trigger The trigger for which this is an output. 104 * @param outputType An enum that specifies the output on the trigger to represent. 105 */ 106 public AnalogTriggerOutput(AnalogTrigger trigger, final Type outputType) { 107 if (trigger == null) 108 throw new NullPointerException("Analog Trigger given was null"); 109 m_trigger = trigger; 110 m_outputType = outputType; 111 112 UsageReporting.report(UsageReporting.kResourceType_AnalogTriggerOutput, trigger.getIndex(), outputType.value); 113 } 114 115 public void free() { 116 } 117 118 /** 119 * Get the state of the analog trigger output. 120 * @return The state of the analog trigger output. 121 */ 122 public boolean get() { 123 switch (m_outputType.value) { 124 case Type.kInWindow_val: 125 return tAnalogTrigger.readOutput_InHysteresis((byte) m_trigger.m_index); 126 case Type.kTypeState_val: 127 return tAnalogTrigger.readOutput_OverLimit((byte) m_trigger.m_index); 128 case Type.kRisingPulse_val: 129 case Type.kFallingPulse_val: 130 throw new AnalogTriggerOutputException("Cannot get the state of the analog trigger output if it is configured for a rising or falling edge"); 131 } 132 // Should never get here. 133 return false; 134 } 135 136 public int getChannelForRouting() { 137 return (m_trigger.m_index << 2) + m_outputType.value; 138 } 139 140 public int getModuleForRouting() { 141 return m_trigger.m_index >> 2; 142 } 143 144 public boolean getAnalogTriggerForRouting() { 145 return true; 146 } 147 148 /** 149 * Request interrupts asynchronously on this digital input. 150 * @param handler the interrupt service routine 151 * @param param a parameter for the ISR 152 */ 153 // public void requestInterrupts(/*tInterruptHandler*/Object handler, Object param) { 154 //TODO: add interrupt support 155 //TODO: throw exception 156 // } 157 158 /** 159 * Request interrupts synchronously on this digital input. 160 */ 161 // public void requestInterrupts() { 162 //TODO: throw exception 163 // } 164 }