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 final double m_debounceTimeSeconds; 025 private final 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 switch (m_debounceType) { 044 case kBoth: // fall-through 045 case kRising: 046 m_baseline = false; 047 break; 048 case kFalling: 049 m_baseline = true; 050 break; 051 default: 052 throw new IllegalArgumentException("Invalid debounce type!"); 053 } 054 } 055 056 /** 057 * Creates a new Debouncer. Baseline value defaulted to "false." 058 * 059 * @param debounceTime The number of seconds the value must change from baseline for the filtered 060 * value to change. 061 */ 062 public Debouncer(double debounceTime) { 063 this(debounceTime, DebounceType.kRising); 064 } 065 066 private void resetTimer() { 067 m_prevTimeSeconds = MathSharedStore.getTimestamp(); 068 } 069 070 private boolean hasElapsed() { 071 return MathSharedStore.getTimestamp() - m_prevTimeSeconds >= m_debounceTimeSeconds; 072 } 073 074 /** 075 * Applies the debouncer to the input stream. 076 * 077 * @param input The current value of the input stream. 078 * @return The debounced value of the input stream. 079 */ 080 public boolean calculate(boolean input) { 081 if (input == m_baseline) { 082 resetTimer(); 083 } 084 085 if (hasElapsed()) { 086 if (m_debounceType == DebounceType.kBoth) { 087 m_baseline = input; 088 resetTimer(); 089 } 090 return input; 091 } else { 092 return m_baseline; 093 } 094 } 095}