Friday, June 5, 2020

Reset And Panic Buttons, Buttons Debouncing


Reset And Panic Buttons, Buttons Debouncing

The monitor program in my home brew computer has a nice debug feature. The NMI (Non-Maskable Interrupt) is used to service the so called 'panic' button. The role of a panic button in a microprocessor system is simple - if your program gets stuck or runs away, you can press the panic button connected to /NMI pin of the processor and the service routine assigned for NMI will store the current program status on the stack, including the return address, dump CPU registers and do whatever else you programmed it to do and then drop you back in the monitor program prompt thus giving you back control without the need to reset the system. You can then use monitor program functions to examine or alter memory of the faulty program and even continue the faulty program execution from the moment of NMI interrupt, if you think you corrected the cause of the problem.
I used that button often to recover from failed / hung up code or to return from 3-rd party applications I ran on my system (e.g.: Tiny Basic) to the monitor prompt. The continuation of the execution didn't work too well though simply because I didn't have the so called debouncing circuit implemented for the panic button.
What is debouncing and why do I need to debounce a button, you might ask?
When you deal with electronic circuits, which involve fast switching signals, you need to realize that in real life applications, things like buttons / switches, wires, connectors, resistors, capacitors, inductors and so on are not perfect. Wires have a resistance and capacitance. Resistors have a capacitance and inductance. Inductors have a resistance. If wires carry high frequency signal, there is interference. In case of mechanical switches the problem is that their contacts bounce off each other – literally and very fast. When you press a button, two metal surfaces come in contact with each other. These surfaces are not perfect. They may be not aligned perfectly. They are not perfectly flat. Over a very small amount of time there is a mechanical high frequency oscillation when these surfaces come in contact and detach from each other before they finally settle. This period of unstable / undefined connection between these surfaces is called bouncing.
To you this looks like a single button push. If you had a battery and light bulb circuit that such button closes, you would just see that the light comes on – and when you release button, the light comes off. To a micro controller or a microprocessor which are usually clocked with relatively high frequency and process the data much quicker than human perception allows to notice, the moment of you pressing the button appears like tens, hundreds or even thousands of separate signal switching events. However we want to register just one clean push. How to solve this dilemma?
There are two major ways – solve it with hardware or with software.
In our case software debouncing will not work, because NMI signal is Non-Maskable (can't be turned off) and is triggered by a low coming signal edge – button contacts bouncing results in a series of high-to-low edges of signals which will trigger a new NMI each time such edge is detected, assuming there was enough time between them to be detected by CPU. Therefore we cannot just mask interrupts at the entrance of NMI service and put a delay on it to ignore the oscillations.
We have to debounce the button in hardware.
One of the cheap and reliable methods to do this which I used in my circuit is to combine RC filter with hysteresis by the means of Schmitt trigger TTL gate, e.g.:  inverting gates found inside 74LS14 or 74HC14 TTL chip. (it has 6 of such gates)
The RC circuit at input to the gate provides low-pass filter to cut off high frequency oscillations resulting from bouncing and Schmitt trigger gate ensures that the on / off levels are separated by a dead zone – pretty much in the same manner that your A/C or heating system thermostat does.

Below is the result. Note that I also debounced the Reset button, however this is not as critical as NMI since /RES in MOS6502 is triggered (and held) by low level. You'll notice though that the capacitor in RC circuit for Reset button is of much higher value than for the Panic button. It is because there is unstable period when you turn on the power to microprocessor system when voltage and currents in the system oscillate before they reach stabilized levels. It is critical that after you turn on the power to the system, the initial reset pulse comes some time after power to all the system components has stabilized. It (/RES signal) also needs to come after any possible unstable oscillations from NMI debouncing circuit, otherwise the system may freeze at startup. It also needs to be at TTL high level when stable, since /RES is active low - thus two inverting gates are used, while it does not matter for NMI sigal which is triggered by the signal's edge, not by its level.


Now I can enjoy reliable panic button function to debug my software or temporarily switch to monitor program to load data, change memory contents etc.

Thanks for reading.

MK 6/5/2020

Credits:
Embed With Elliot: "DEBOUNCE YOUR NOISY BUTTONS, PART I"

References:
Schmitt Trigger Gate
DM74LS14: Hex Inverter with Schmitt Trigger Inputs


Reset And Panic Buttons, Buttons Debouncing

Reset And Panic Buttons, Buttons Debouncing The monitor program in my home brew computer has a nice debug feature. The NMI (Non-Maskab...