001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) FIRST 2015-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 java.util.concurrent.locks.Lock; 011import java.util.concurrent.locks.ReentrantLock; 012 013import edu.wpi.first.wpilibj.hal.DigitalGlitchFilterJNI; 014import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType; 015import edu.wpi.first.wpilibj.hal.HAL; 016 017/** 018 * Class to enable glitch filtering on a set of digital inputs. This class will manage adding and 019 * removing digital inputs from a FPGA glitch filter. The filter lets the user configure the time 020 * that an input must remain high or low before it is classified as high or low. 021 */ 022public class DigitalGlitchFilter extends SensorBase { 023 024 /** 025 * Configures the Digital Glitch Filter to its default settings. 026 */ 027 public DigitalGlitchFilter() { 028 synchronized (m_mutex) { 029 int index = 0; 030 while (m_filterAllocated[index] != false && index < m_filterAllocated.length) { 031 index++; 032 } 033 if (index != m_filterAllocated.length) { 034 m_channelIndex = index; 035 m_filterAllocated[index] = true; 036 HAL.report(tResourceType.kResourceType_DigitalFilter, 037 m_channelIndex, 0); 038 } 039 } 040 } 041 042 /** 043 * Free the resources used by this object. 044 */ 045 public void free() { 046 if (m_channelIndex >= 0) { 047 synchronized (m_mutex) { 048 m_filterAllocated[m_channelIndex] = false; 049 } 050 m_channelIndex = -1; 051 } 052 } 053 054 private static void setFilter(DigitalSource input, int channelIndex) { 055 if (input != null) { // Counter might have just one input 056 // analog triggers are not supported for DigitalGlitchFilters 057 if (input.isAnalogTrigger()) { 058 throw new IllegalStateException("Analog Triggers not supported for DigitalGlitchFilters"); 059 } 060 DigitalGlitchFilterJNI.setFilterSelect(input.getPortHandleForRouting(), channelIndex); 061 062 int selected = DigitalGlitchFilterJNI.getFilterSelect(input.getPortHandleForRouting()); 063 if (selected != channelIndex) { 064 throw new IllegalStateException("DigitalGlitchFilterJNI.setFilterSelect(" 065 + channelIndex + ") failed -> " + selected); 066 } 067 } 068 } 069 070 /** 071 * Assigns the DigitalSource to this glitch filter. 072 * 073 * @param input The DigitalSource to add. 074 */ 075 public void add(DigitalSource input) { 076 setFilter(input, m_channelIndex + 1); 077 } 078 079 /** 080 * Assigns the Encoder to this glitch filter. 081 * 082 * @param input The Encoder to add. 083 */ 084 public void add(Encoder input) { 085 add(input.m_aSource); 086 add(input.m_bSource); 087 } 088 089 /** 090 * Assigns the Counter to this glitch filter. 091 * 092 * @param input The Counter to add. 093 */ 094 public void add(Counter input) { 095 add(input.m_upSource); 096 add(input.m_downSource); 097 } 098 099 /** 100 * Removes this filter from the given digital input. 101 * 102 * @param input The DigitalSource to stop filtering. 103 */ 104 public void remove(DigitalSource input) { 105 setFilter(input, 0); 106 } 107 108 /** 109 * Removes this filter from the given Encoder. 110 * 111 * @param input the Encoder to stop filtering. 112 */ 113 public void remove(Encoder input) { 114 remove(input.m_aSource); 115 remove(input.m_bSource); 116 } 117 118 /** 119 * Removes this filter from the given Counter. 120 * 121 * @param input The Counter to stop filtering. 122 */ 123 public void remove(Counter input) { 124 remove(input.m_upSource); 125 remove(input.m_downSource); 126 } 127 128 /** 129 * Sets the number of FPGA cycles that the input must hold steady to pass through this glitch 130 * filter. 131 * 132 * @param fpgaCycles The number of FPGA cycles. 133 */ 134 public void setPeriodCycles(int fpgaCycles) { 135 DigitalGlitchFilterJNI.setFilterPeriod(m_channelIndex, fpgaCycles); 136 } 137 138 /** 139 * Sets the number of nanoseconds that the input must hold steady to pass through this glitch 140 * filter. 141 * 142 * @param nanoseconds The number of nanoseconds. 143 */ 144 public void setPeriodNanoSeconds(long nanoseconds) { 145 int fpgaCycles = (int) (nanoseconds * kSystemClockTicksPerMicrosecond / 4 146 / 1000); 147 setPeriodCycles(fpgaCycles); 148 } 149 150 /** 151 * Gets the number of FPGA cycles that the input must hold steady to pass through this glitch 152 * filter. 153 * 154 * @return The number of cycles. 155 */ 156 public int getPeriodCycles() { 157 return DigitalGlitchFilterJNI.getFilterPeriod(m_channelIndex); 158 } 159 160 /** 161 * Gets the number of nanoseconds that the input must hold steady to pass through this glitch 162 * filter. 163 * 164 * @return The number of nanoseconds. 165 */ 166 public long getPeriodNanoSeconds() { 167 int fpgaCycles = getPeriodCycles(); 168 169 return (long) fpgaCycles * 1000L 170 / (long) (kSystemClockTicksPerMicrosecond / 4); 171 } 172 173 private int m_channelIndex = -1; 174 private static final Lock m_mutex = new ReentrantLock(true); 175 private static final boolean[] m_filterAllocated = new boolean[3]; 176}