calamari Posted March 4, 2002 Share Posted March 4, 2002 Woohoo!! I found what I needed in the Atari System Reference Manual, Chapter 5 "THE KEYBOARD HANDLER". When the Keypad IRQ is entered., what you do is check to see if this key is the same as the last key. If not, cool, accept the key and go on. If it's the same, check a debounce counter (we make this ourselves). If this counter is zero, then the key is accepted, otherwise its discarded as a held down key. In all cases of entry into the Keypad IRQ the debounce is reset to 3 (you can experiment with other values but this seems okay). This resets the counter.. so when a key is held down this will always be 3. Now, in the deferred VBI, the debounce counter is decremented until its zero, one step at a time (3 2 1 0). If my math is correct, this means once you let go of a key, you have to wait 1/20 of a second before pushing it again. Considering the 5200 keypads, this should not be a serious problem Here is source code for the Keypad DLI and deferred VBI routines. This code has been tested and is working great on the real 5200!: code: ; Zero page equates KEY .EQU $2A ; this is similar to the Atari 800 CH KEYLAST .EQU $2B KEYDB .EQU $2C ;--------------------------------------------------------------------- ; KEYPAD -- Keypad buffer handler ; On entry: A=key just pressed ;--------------------------------------------------------------------- .ORG $BC00 CMP KEYLAST ;same key as last time? BNE KEYOK LDX KEYDB ;same key, check debounce timer BNE KEYDONE ;if debounce isn't 0, reject the key KEYOK STA KEY STA KEYLAST ;store keypress KEYDONE LDA #$03 ;reset debounce timer STA KEYDB PLA TAY ;POP Y PLA TAX ;POP X PLA ;POP A RTI ;--------------------------------------------------------------------- ; Deferred VBI handler ;--------------------------------------------------------------------- .ORG $BC20 LDA KEYDB ;check key debounce counter BEQ VBIDONE ;if zero, skip DEC KEYDB ;otherwise decrease by one VBIDONE PLA TAY ;POP Y PLA TAX ;POP X PLA ;POP A RTI I'm glad that's finally out of the way! calamari [ 03-04-2002: Message edited by: calamari ] Quote Link to comment Share on other sites More sharing options...
DEBRO Posted March 4, 2002 Share Posted March 4, 2002 Okay you're going to have to explain this one to me. The ANALOG article mentions that the debounce circuit does not have to be set on the 5200. I also looked at the BIOS and I don't see where this count down is taking place. Am I missing it? The VBI does the timer, checks the critical code, updates DLISTH, DLISTL , and DMACTL from the shadows, check the attract mode, and update the POT registers. Where is it? Quote Link to comment Share on other sites More sharing options...
calamari Posted March 4, 2002 Author Share Posted March 4, 2002 DEBRO, Okay, let me try again! Take a look at the code while you read this, too. You're right, we aren't going to use any debounce circuitry (I tried setting that debounce enable bit and it would lock up the keypad on the real 5200). So, that means we have to make our own little debouncer algorithm. The first step to doing that is understanding where the problems are and what we want to happen instead. On the real 5200, SKSTAT doesn't act like it does on the emulator (take a look at DEBUG52, and view address $E80F.. see how it is $FF then stays $FB while a key is pressed? Not so on the 5200, it is mostly $FF with an occasional $FB). So, we can't use SKSTAT to tell us when the key is no longer held. And there is no interrupt that is fired when a key is released, so it would seem that we are out of options... except we can use time to our advantage. Have you ever used a tape recorder with the little counter on it, where if you push the button it resets the counter to all zeros, then if you let go it starts counting upward again? That's exactly what we are going to do. When a keypad button is held it continually sets our fake debounce counter to 3. Then, when we let go of the keypad button the vertical blanking interrupt subtracts 1 from it each time it's called (every 1/60th of a second or so). So, if a key is not pushed then this counter will eventually hit zero, but it will take time to do so. When we are deciding whether to accept a new keystroke or not, first we'll check this counter.. if its zero, then we are pretty sure there is no key being held so we accept the new key. If its not zero, then the key might still be held.. but, if the key is different from last time then the last one its obviously not being held so we accept the new key. Otherwise, the new key is rejected. Hope that helps, calamari Quote Link to comment Share on other sites More sharing options...
DEBRO Posted March 4, 2002 Share Posted March 4, 2002 Sorry, I see what you're doing now. You are writing your own debounce routine. When I first read it I thought you were using a routine from the BIOS. Did you try using the keypad interrupt for your repeat check? Since the keypad interrupt is only called when a key is pressed (at least on the emulators )then the repeat could be solved that way. You could use a gamestate variable to hold off whether the player is on the selection screen or in game play. Then only use the keys that are relevent to the gamestate. Then you would use possibly two bytes (key pressed and gamestate) as opposed to 3. Just a thought but your idea is a good one too. Quote Link to comment Share on other sites More sharing options...
calamari Posted March 5, 2002 Author Share Posted March 5, 2002 Go ahead and try it! if it works, please share with the rest of us So far, this is all I have found that works. calamari Quote Link to comment Share on other sites More sharing options...
DEBRO Posted May 30, 2002 Share Posted May 30, 2002 * BUMP * OldGuru tried the technique I described above and confirmed that the key repeat problem happens with the interrupt too. After looking at the Tempest disassembly I saw that they use a debounce routine too. Here is what is done... Variable $029E is incremented in the VBI until it reaches #$80. This variable is then used in the keypad interrupt. When ever the keypad is pressed the variable is reset to #$00. If the value before entering the routine is less than #$05 the keypad routine is skipped. Here's a snipplet: code: VBIDeferred . . . L8106 lda keypadDebounce bmi L810E inc keypadDebounce L810E jsr L9C00 . . . KBCodeVector ldx keypadDebounce ; Get keypad debounce value ldy #$00 sty keypadDebounce ; Reset keypad debounce value sty ATRACT ; Reset attract mode cpx #$05 ; if keypad debounce < #$05 leave keypad routine bcc ExitKBCodeVector . . . Quote Link to comment Share on other sites More sharing options...
calamari Posted May 30, 2002 Author Share Posted May 30, 2002 Wow that's not too far off from my routine (of course it looks to be a little more efficient). That's cool.. it makes me feel like I know what I'm doing Thanks, calamari p.s. I haven't been doing much on Solitare lately.. All I've been doing is going to work and school. I still need to write my new sprite routine, and it's turning out to be more of a challenge than I expected. Once I get it, it will be great though! Quote Link to comment Share on other sites More sharing options...
+Cafeman Posted May 31, 2002 Share Posted May 31, 2002 I still haven't put in a keypad debounce into Koffi. The most irritating thing is to try and select which level / stage with a repeating keypad button! Once I get the Pocket Programmer, I'll feel safer about throwing this in & testing it out for myself. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.