001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.math.filter; 006 007import edu.wpi.first.math.MathSharedStore; 008 009/** 010 * A simple debounce filter for boolean streams. Requires that the boolean change value from 011 * baseline for a specified period of time before the filtered value changes. 012 */ 013public class Debouncer { 014 /** Type of debouncing to perform. */ 015 public enum DebounceType { 016 /** Rising edge. */ 017 kRising, 018 /** Falling edge. */ 019 kFalling, 020 /** Both rising and falling edges. */ 021 kBoth 022 } 023 024 private double m_debounceTimeSeconds; 025 private DebounceType m_debounceType; 026 private boolean m_baseline; 027 028 private double m_prevTimeSeconds; 029 030 /** 031 * Creates a new Debouncer. 032 * 033 * @param debounceTime The number of seconds the value must change from baseline for the filtered 034 * value to change. 035 * @param type Which type of state change the debouncing will be performed on. 036 */ 037 public Debouncer(double debounceTime, DebounceType type) { 038 m_debounceTimeSeconds = debounceTime; 039 m_debounceType = type; 040 041 resetTimer(); 042 043 m_baseline = m_debounceType == DebounceType.kFalling; 044 } 045 046 /** 047 * Creates a new Debouncer. Baseline value defaulted to "false." 048 * 049 * @param debounceTime The number of seconds the value must change from baseline for the filtered 050 * value to change. 051 */ 052 public Debouncer(double debounceTime) { 053 this(debounceTime, DebounceType.kRising); 054 } 055 056 private void resetTimer() { 057 m_prevTimeSeconds = MathSharedStore.getTimestamp(); 058 } 059 060 private boolean hasElapsed() { 061 return MathSharedStore.getTimestamp() - m_prevTimeSeconds >= m_debounceTimeSeconds; 062 } 063 064 /** 065 * Applies the debouncer to the input stream. 066 * 067 * @param input The current value of the input stream. 068 * @return The debounced value of the input stream. 069 */ 070 public boolean calculate(boolean input) { 071 if (input == m_baseline) { 072 resetTimer(); 073 } 074 075 if (hasElapsed()) { 076 if (m_debounceType == DebounceType.kBoth) { 077 m_baseline = input; 078 resetTimer(); 079 } 080 return input; 081 } else { 082 return m_baseline; 083 } 084 } 085 086 /** 087 * Sets the time to debounce. 088 * 089 * @param time The number of seconds the value must change from baseline for the filtered value to 090 * change. 091 */ 092 public void setDebounceTime(double time) { 093 m_debounceTimeSeconds = time; 094 } 095 096 /** 097 * Gets the time to debounce. 098 * 099 * @return The number of seconds the value must change from baseline for the filtered value to 100 * change. 101 */ 102 public double getDebounceTime() { 103 return m_debounceTimeSeconds; 104 } 105 106 /** 107 * Sets the debounce type. 108 * 109 * @param type Which type of state change the debouncing will be performed on. 110 */ 111 public void setDebounceType(DebounceType type) { 112 m_debounceType = type; 113 114 m_baseline = m_debounceType == DebounceType.kFalling; 115 } 116 117 /** 118 * Gets the debounce type. 119 * 120 * @return Which type of state change the debouncing will be performed on. 121 */ 122 public DebounceType getDebounceType() { 123 return m_debounceType; 124 } 125}