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.util.WPIUtilJNI; 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 public enum DebounceType { 015 kRising, 016 kFalling, 017 kBoth 018 } 019 020 private final double m_debounceTimeSeconds; 021 private final DebounceType m_debounceType; 022 private boolean m_baseline; 023 024 private double m_prevTimeSeconds; 025 026 /** 027 * Creates a new Debouncer. 028 * 029 * @param debounceTime The number of seconds the value must change from baseline for the filtered 030 * value to change. 031 * @param type Which type of state change the debouncing will be performed on. 032 */ 033 public Debouncer(double debounceTime, DebounceType type) { 034 m_debounceTimeSeconds = debounceTime; 035 m_debounceType = type; 036 037 resetTimer(); 038 039 switch (m_debounceType) { 040 case kBoth: // fall-through 041 case kRising: 042 m_baseline = false; 043 break; 044 case kFalling: 045 m_baseline = true; 046 break; 047 default: 048 throw new IllegalArgumentException("Invalid debounce type!"); 049 } 050 } 051 052 /** 053 * Creates a new Debouncer. Baseline value defaulted to "false." 054 * 055 * @param debounceTime The number of seconds the value must change from baseline for the filtered 056 * value to change. 057 */ 058 public Debouncer(double debounceTime) { 059 this(debounceTime, DebounceType.kRising); 060 } 061 062 private void resetTimer() { 063 m_prevTimeSeconds = WPIUtilJNI.now() * 1e-6; 064 } 065 066 private boolean hasElapsed() { 067 return (WPIUtilJNI.now() * 1e-6) - m_prevTimeSeconds >= m_debounceTimeSeconds; 068 } 069 070 /** 071 * Applies the debouncer to the input stream. 072 * 073 * @param input The current value of the input stream. 074 * @return The debounced value of the input stream. 075 */ 076 public boolean calculate(boolean input) { 077 if (input == m_baseline) { 078 resetTimer(); 079 } 080 081 if (hasElapsed()) { 082 if (m_debounceType == DebounceType.kBoth) { 083 m_baseline = input; 084 resetTimer(); 085 } 086 return input; 087 } else { 088 return m_baseline; 089 } 090 } 091}