Button Handler
Mag748
Posts: 266
Hi there,
I'm working on a project that will involve lots of button input. So I'd like to design a really efficient button handler. I have already gotten the actual reading of the buttons and debouncing code. I'd like to now move onto the "event handling" portion. What I mean is the code that actually monitors the debounced button data to determine when a button is pressed once, pressed and held, and double pressed. This handler needs to be able to monitor up to 24 individual buttons simultaneously.
The simplest way would be to just loop through each button, set timers and whatnot, and maybe set a flag when a button press, or double press or whatever happens. But then I need flags for each buttons x 24. And I feel like that would be clunky. I was thinking maybe a better way would be to create an event buffer. So, this method could monitor all buttons simultaneously, and when is detects that button 6 was just double pressed, is adds a "button 6 double press" to a stack or something. How does this idea sound? And does anyone have any examples of something like this that already exists?
Thanks a lot,
Marcus
I'm working on a project that will involve lots of button input. So I'd like to design a really efficient button handler. I have already gotten the actual reading of the buttons and debouncing code. I'd like to now move onto the "event handling" portion. What I mean is the code that actually monitors the debounced button data to determine when a button is pressed once, pressed and held, and double pressed. This handler needs to be able to monitor up to 24 individual buttons simultaneously.
The simplest way would be to just loop through each button, set timers and whatnot, and maybe set a flag when a button press, or double press or whatever happens. But then I need flags for each buttons x 24. And I feel like that would be clunky. I was thinking maybe a better way would be to create an event buffer. So, this method could monitor all buttons simultaneously, and when is detects that button 6 was just double pressed, is adds a "button 6 double press" to a stack or something. How does this idea sound? And does anyone have any examples of something like this that already exists?
Thanks a lot,
Marcus
Comments
I'm afraid the program may have likely has bugs. I'll likely revisit the object soon since I have another 16 key keypad I'm using in one of my current projects.
Another option to using a matrix to detect the button presses, is to use '165 parallel to serial shift registers. You could shift in the bits to obtain the current button states and use only three I/O pins on the Propeller.
The trick for me was deciding what is reasonable in terms of timing. For instance, I remember selecting 100msec as a reasonable time between button presses. Deciding how long is "holding" the button and how long much time between presses defines a "double tap", then the rest of the code almost writes itself.
I am converting some of my code from BS2p to PropBASIC for MCP23S17, if an example of initializing at setting the various registers would help. In fact, the next thing that I will be cleaning up is a 8-input scheme (3 push-buttons and 5 lines from HT12 Decoder).
IMHO the determination of whether the button is pressed once, pressed and held, or double pressed should be done in the button reading/debouncing code, and the result returned in some manner. Perhaps you could return a byte with 5 bits indicating the button and 3 bits used for how it was pressed.
Is the button reading/debouncing done in spin, pasm, or something else?
Could you imagine if your keyboard used double clicks? You'd have to be very careful whenever typing words with double letters.
I like the idea of using the FIFO to buffer button events. Instead of worrying about the "timeToLive" timer, I'll probably just circle around and over write the oldest event if the buffer is not read fast enough. Are there any robust example of FIFO buffers out there? Maybe that use ASM as well? Duane, I will look through your example because it does look promising.
phatallica, kwinn,
I am going to keep the button state gathering/debouncing completely separate from the event handler. That way I can pass any type of input to the handler, whether it from from a Prop pin, a '165 or any other input device. I'm trying to may this as universal and plug and play as possible.
Duane,
I do agree that it seems unnecessary to have the ability of a double press/long press on every single input. But I thought for simplicity and "expandability", creating the system to work with 1 button should be the same for as many buttons as you need. It would just be a matter of requiring more memory and maybe a little more processing time per additional button. I don't want the method I write to be too specialized and specific to one application.
Thanks for the input. I will go with a circular buffer and try and figure out how to make this object modular enough to be useful. I'll update this thread with progress I make.
Thanks,
Marcus
The idea was, if the keypad were pressed accidentally when data isn't expected, the key press wouldn't remain in the buffer. I didn't want an old key press to be the first entry when I switched the device to a mode expecting data.
Most (probably all) of the serial objects use circular buffers. All the objects I've looked at (I've looked at many) drop all the data in the buffer once the head meets the tail. It would require some additional code to have the buffer drop the oldest data and preserve the rest. I can't think of many situations where you would want to keep partial data.
As I mentioned previously, it was a very early attempt. I'm pretty sure it's buggy.
I look forward to seeing what you come up with.
I am just wondering how you plan to distinguish between a single button press, a button being held down, or a button being pressed twice if it is not done in the button reading/debouncing routine. I can see that having the same key code appear twice in the buffer could indicate a button was pressed twice, but how will you tell if it was pressed and held?
This is why I suggested that the trick is defining a reasonable human interface input. Once you plot out the timing for each, I suspect that it will be a graphical representation of the pseudocode. For instance (arbitrary values):
1msec = software debounce
1sec = duration of press & hold
500msec = allowable gap between presses for double press.
100msec = minimum time between different button presses (rate of 10/sec).
Maybe Marcus has a better plan already?
The program that reads the buffer would need more info than just the key, a double click key should have an extra MSBit set.
If your buffer can store key 0-127, but with bit 7 set (now a value between 128-255) represent the same key but double clicked.