That looks interesting, thanks!
What I have done in the past is debounce by waiting for 10 mS from the last bounce. That is, after the switch is pressed you remember the time. If another bounce happens you reset the timer (that is, remember the new time). Once 10 mS elapses and no further bounces then you consider the bouncing over. This gives a quick recovery from a short bounce, but guarantees that you will properly handle multiple bounces.
A simpler delay-based algorithm like the one you describe works well if button presses are relatively isolated in time (if the time interval between button presses will be longer than the longest possible bounce period).
But in my case, I needed to detect button presses that may come only 100-150 ms from one another. With my tactile button, the duration of the bouncing was quite variable, with some (very few, but some nonetheless) button presses generating noise for more than 100 ms. Since that exceeds the resolution with which I must detect button presses, delay-based algorithms did not work for me.
The benefit of an RC / Schmitt trigger solution (whether hardware or software-emulated) is that it constantly smooths out the state change information coming from the pin rather than imposing a fixed "blackout" period where the pin is ignored for a certain amount of time or, even less usefully, for a fixed number of state changes. The smoothing is accomplished by the RC circuit in a hardware solution, or by the following recursive algorithm in the software solution:
filteredPinstate = (newPinstate * 0.25) + (filteredPinstate * 0.75);
The algorithm only recognizes a true pin state change if the filteredPinstate rises (or falls) to a certain threshold (there is hysteresis, so there are different thresholds for rising and falling). Because this threshold is less than a logical 1 for a valid 1 to be registered, and more than a logical 0 for a 0 to be registered, the algorithm is able to recognize a true pin state change even if the pin state is still bouncing slightly.
In other words, a pin state change is recognized not when bouncing ceases completely, but when the pin BEGINS to settle down (and based on both experience and research, buttons are mostly settled within 20 or so milliseconds after a button press, with only occasional spikes occurring up to 150-200 ms after that). Thanks to the hysteresis, this does not result in an error if the button is re-pressed while some bouncing from the prior button press is going on -- so long as the bouncing from the prior button press has settled down sufficiently for the algorithm to recognize a valid button press (this is where the Schmitt trigger thresholds, 240 and 15 in my code, can be tuned).
This theory works in practice. I tried out a number of different momentary buttons (OK, I only had three different tactile switches on hand
), and when the requirement is to be able to recognize button presses that are as little as 100-150 ms apart, this algorithm works flawlessly (so far). I have tried at least a dozen various delay-based or counter-based debounce solutions, and not a single one was able to eliminate all bounce while still recognizing all button presses.
I thought that was fairly complicated.
My code was heavily commented and broken down to make it easier to read. The operative portion is only about 10 lines of code. And the moderate complexity of the code yields a result that your code does not -- functional debouncing in the scenario I describe above.
In any event, it's never a good idea to debounce solely based on count of pin state changes without some sort of timeout also being implemented, especially when using polling rather than interrupts for detecting button presses, because some button presses are clean and do not generate ANY bouncing, whereas other presses of the same button can generate 2, 10, or 300 (or any arbitrary number) of false state changes. See http://www.ganssle.com/debouncing.htm
Imposing a "blackout" based on the number of pin state changes will therefore miss many button presses.