Switch debouncing

Switch bouncing is non-ideal behavior of the contacts that creates multiple electrical transitions for a single button push or release. Pretty much every switch or button that has a spring in it is subject to bounce.

One of the approaches to handle the switch bouncing is to check the button state (on/off) every 10 to 20 ms and store the states in a byte variable.
That is, b7b6b5b4b3b2b1b0 presents a history of 8 most recent checks. The oldest button state is b0 and the most recent button state is b7 (bi=1 is button is off and 0 otherwise).
This variable is updated in a shift register after every button status check. The old variable value is shifted right on 1 bit, and the new bit is inserted as bit7.

b7b6b5b4b3b2b1b0   ⇒   0 b7b6b5b4b3b2b1   ⇒   newb7b6b5b4b3b2b1

We accept the button status as ON (pressed) if the button was detected to be pressed at least for the last two checkings (b7=b6=0).
In other terms, the variable value is of the form 00xxxxxx, where x are the remaining bits in the shift register.
This way we introduce a constant press_threshold = 00111111 = 0x3F.
Therefore, once the shift register value after the next check becomes less or equal to press_threshold, we accept the new button state as ON.

Similarly the debouncing can be performed when the button is released.
It turns out that tactile buttons bounce more when they are released compared to pressing them.
We address this situation by waiting for the button to be OFF (released) at least for the last 6 checkings, i.e. 111111xx.
That is, the value in the shift register must be not less that release_threshold = 11111100 = 0xFC for the button state to change from ON to OFF.

Putting all together, for every button we allocate a 1-byte variable shift_reg and a binary variable state indicating its state (1 = OFF, 0 = ON).
The debouncing algorithm consists of periodic repetition of steps 1 to 3 in the following pseudocode:

0. shift_reg = 0xFF; state = OFF  // initialization
1. new = current button value     // 1="OFF" 0="ON"
2. shift_reg = (shift_reg >> 1) + (new << 7)
3. if (state == OFF)              // check old state
   {
     if (shift_reg <= press_threshold)
     {
       state = ON                 // new state
       perform needed tasks       // button press is detected
     }
   }
   else                           // old state is ON 
   {
     if (shift_reg >= release_threshold)
     {                            // button release is detected
       state = OFF                // just update button state
                                  // usually do nothing else here
     } 
   }