#3067 - Vortex - Mon Feb 17, 2003 5:04 pm
Hello,
I have problems with my keypad debouncing code. In 95% of the cases it works just fine. The problem appears when more than one button is pressed. In that case the code seems to repeat one of the pressed code until the same button is pressed again. I will be very gratefull if you can point my error or provide a better debouncing example.
Thanks
Code: |
u16 kbd = 0x03FF;
u16 debounce = 0x03FF;
debounce = kbd = 0x03FF;
while(1)
{
u16 keys = *KEYS;
if( keys != kbd )
{
debounce &= keys;
kbd = keys;
}
else
{
debounce |= ~kbd;
debounce &= 0x03FF;
}
if(!(debounce & KEY_LEFT))
{
//...
}
else if(!(debounce & KEY_RIGHT))
{
//...
}
}
|
#3082 - ampz - Mon Feb 17, 2003 10:16 pm
I have no idea what you are trying to accomplish with that piece of code.
Whatever it is, it's not keypad debouncing.
Looks just weird to me.
#3083 - kyp4 - Mon Feb 17, 2003 10:18 pm
What exactly is keypad debouncing, just out of cuiriosity. I've never heard that term before.
#3084 - Daikath - Mon Feb 17, 2003 10:23 pm
Heh, I rememver you from the mIRC chat :)
That is indeed not keypas deboucing but tile debouncing. If a player is about to walk to a tile like some piece of stone he cant walk accross it. But it failes if someone presses both up and left when he is touching the stone, now I see the stone I notice that it only handles the events wherein either 4 direction buttons are pressed, maybe if you count 8 it would solve the problem.
_________________
?There are no stupid questions but there are a LOT of inquisitive idiots.?
#3085 - Vortex - Mon Feb 17, 2003 10:33 pm
ampz wrote: |
I have no idea what you are trying to accomplish with that piece of code.
Whatever it is, it's not keypad debouncing.
Looks just weird to me. |
If you have a better idea why don't you share with us ?
#3086 - Daikath - Mon Feb 17, 2003 10:56 pm
Heh, wasn''t from the mIRC chat lol :).
_________________
?There are no stupid questions but there are a LOT of inquisitive idiots.?
#3087 - Paul Shirley - Mon Feb 17, 2003 11:04 pm
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:41 pm; edited 1 time in total
#3088 - Vortex - Mon Feb 17, 2003 11:15 pm
Paul Shirley wrote: |
If you tell us what its meant to do maybe we will. Meanwhile get a better attitude.
That's certainly not debounce code (not that you need it on a GBA) and its totally broken if its trigger detection (should be pure bitwise ops not conditional).
|
Sorry, no offence was intended.
My goal was to implement the debouncing as described by Splam:
Quote: |
Yep, you can debounce the buttons. GBA doesn't have its own.
obviously if you know how debounce works ignore this post :)
To do it you need to read the register every frame then have a routine that checks it against the previous frames entry. Only if the state has changed (the button has been pressed) do you then set a bit in the "debounce" variable. If the current and previous frames are the same the debounce for that button is cleared.
Your main code then reads the debounce variable to see if anything has been pressed, if you want to know if something is being held down you obviously just check the current frames variable.
Do this at the start of a frame then make sure to read the debounce and process presses every frame else you'll miss the presses as they only happen once per press and are cleared on the next frame (hence the debounce).
-edit-
If you want a sort of in between method so holding a button down still registers but not as often just add a timer to your debounce routine (or use a main game loop timer) if the desired time has passed clear out the debounce variables (last frame one should do it) then the "button pressed" part of the debounce variable will be set again and again etc
|
#3089 - Paul Shirley - Tue Feb 18, 2003 1:24 am
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:41 pm; edited 1 time in total
#3093 - tepples - Tue Feb 18, 2003 4:26 am
Here's code adapted from TOD that implements autorepeat:
Code: |
#define JOY (*(volatile u16 *)0x04000130)
#define REPEAT_DELAY 11 /* in frames */
#define JOYIDX_RIGHT 4
char repeatTime[10];
/* MakeRepeats() ***********************
Autorepeats digital pad motion. After autoDelay calls, it repeats
a key HZ/autoRate times a second.
'j' must be active HIGH, not active low as on e.g. GBA hardware.
*/
void MakeRepeats(char *repeatTime, int j, int autoDelay, int autoRate)
{
int i;
for(i = 0; i < 10; i++)
{
if(j & 0x01)
{
repeatTime[i]++;
if(repeatTime[i] >= autoDelay)
repeatTime[i] -= autoRate;
}
else
{
repeatTime[i] = 0;
}
j >>= 1;
}
}
/* ... */
GameLoop()
{
/* ~JOY converts active-low register contents to active-high */
MakeRepeats(repeatTime, ~JOY, REPEAT_DELAY + 1, 2);
/* ... */
if(repeatTime[JOYIDX_RIGHT] == 1 ||
repeatTime[JOYIDX_RIGHT] == REPEAT_DELAY)
{
/* handle right press */
}
} |
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#3114 - Vortex - Tue Feb 18, 2003 4:24 pm
Thank you, guys for the examples. I really appreciate your help.
After some thinking and googling I came with the following code:
Quote: |
u16 keys, current, down;
u16 previous = 0;
while( game_flag == GAME_CONTINUE ) // Main Loop
{
keys = *KEYS;
keys = keys & 0x03FF;
current = keys;
keys = keys ^ 0x03FF;
keys = keys ^ previous;
delta = keys;
down = delta & previous;
previous = current ^ 0x03FF;
if(down & KEY_LEFT)
{
// Do something
}
else if(down & KEY_RIGHT)
{
// Do something
}
}
|
Probably this is not the best way but it seems to work.
Since we are discussing that topic let me ask you one more question:
Do you see any benefits using interrupt based keypad handling instead of polling ?
The basic idea is to implement something similar to the PC BIOS keyboard handling, i.e. an interrupt handler which writes keycodes into a circular buffer. The program later consumes these keycodes from the buffer.
Thanks again
#3126 - ampz - Tue Feb 18, 2003 7:51 pm
Polling once each frame works well for most applications.
Of course, in some special cases perhaps a interrupt might be preferable. It all depends on what you are trying to do.
#3211 - Paul Shirley - Thu Feb 20, 2003 5:21 am
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:41 pm; edited 1 time in total
#3241 - ampz - Thu Feb 20, 2003 11:07 pm
For some special case text-input applications it might be practical to use the interrupt...
Actually, for most applications where you don't care about VBL.
(That is, very specific and quite odd applications)
Consider some application where you have to really conserve battery power, and you only need to do processing when the user provides some keypad input.
#3244 - mbcook - Thu Feb 20, 2003 11:26 pm
ampz wrote: |
Consider some application where you have to really conserve battery power, and you only need to do processing when the user provides some keypad input. |
Which is definatly not most of the things that you'd put on a gameboy. Some kind of other embedded system, yes; but gameboys usually run games, which usually are always doing things.
_________________
--Michael
#3246 - Paul Shirley - Thu Feb 20, 2003 11:54 pm
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:41 pm; edited 1 time in total
#3261 - ampz - Fri Feb 21, 2003 10:26 am
If you want to conserve power, you can put the GBA into sleep-mode (but keep the screen active), and only wakeup each time the user press a key.
#3277 - CoolMan - Fri Feb 21, 2003 5:26 pm
Sounds slow. :)
_________________
Moron! You don't herd chickens with a shotgun!
--CoolMan