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