Art of a button - Advanced AVR 3.0 Core - Sleep, watchdog, interrupt
Instead of keeping time using a software counter, the long delay time is configured directly using the watchdog timer, since it has a range from 16ms to 2 seconds. The advantage is simpler code and thus more robust result. With this driver, the amount of clicks is limitless as long as the previous button and the current button presses occur within 500ms. The button denounced time is at a fixed 16ms interval. For powering up the MCU, a longer button denounce time can be used, but since double click here is very robust and efficient, double click can be used as the power ON trigger.
Hold to turn on/off is different from press and release and wait for 500ms. Hold trigger doesn't need the button to be released, but a long 500ms holding time is required for it to register, so here the active LOW reading is more important. This is easily implemented with the normal watchdog button denounce timer set to a longer delay period, so normal button denounce is 16ms, power On/Off denounced is 500ms. Switching between these two is controlled by a Boolean power.up. If power.up is 0, then button denounce delay is 500ms, else 16ms.
Power up and power down may seem a simple concept, but it's not as it seems. Here power down boolean is used as a simple way to turn off the MCU in the main loop. Different sleep mode can be picked before setting this switch. Power up is also has nothing to do with the status of which sleep mode the MCU is currently in. It's only used to switch between 16ms and 500ms button debounce delay, so before it's defined as power up, the button is required to be pressed longer than 500ms for the switch to work, a way to avoid accidentally pressing a button. Implementing a hold-500ms to turn ON the MCU works very well like this, but the hold-500ms to turn OFF the MCU is not possible with this cheat, since if the 500ms long button debounce delay is picked, then other double-clicks will not work.
To sum up: 1, single-click the button to turn ON and OFF a LED; 2, double-click the button to change toggle between 2 brightness levels; 3, triple-click to lock the button to 500ms debounce timer, and turning off the MCU and LED; Once locked, the button needs to be hold down for 500ms to switch it back ON.