[ASM] Problem reading the key port (solved)

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

Post Reply
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

[ASM] Problem reading the key port (solved)

Post by Timendus »

Can someone explain to me why Jim's cute little getcsc routine, adapted slightly for Vera...

Code: Select all

    ;; === keyboard_getkey ===
    ;;
    ;; Non-blocking getkey routine
    ;;
    ;; Post:
    ;;   a = key value

    keyboard_getkey:
        push hl
        push de
        push bc
        ld a,$ff
        out (KEYBOARD),a           ; reset keyport
        ld e,$fe                   ; frist group
        ld c,KEYBOARD              ; key port
        ld l,0                     ; l holds key pressed
    keyboard_getkey_loop:
        out (c),e                  ; set keygroup
        ld b,8                     ; loop, Delay needed when work with key driver
        in a,(c)                   ; read key
    keyboard_getkey_bit:
        inc l                      ; inc to get key pressed
        rra                        ; if key pressed done
        jp nc,keyboard_getkey_done
        djnz keyboard_getkey_bit   ; loop 8
        rlc e                      ; next key group
        jp m,keyboard_getkey_loop  ; if bit 7 set loop
        ld l,0                     ; if no key pressed 0
    keyboard_getkey_done:
        ld a,l
        pop bc
        pop de
        pop hl
        ret
...is outputting three or four different values for each key, at random? It took me a while to understand it, but now I do I can't see anything wrong with it... Could it have something to do with delays? Here you can see me pressing Enter eight times in PindurTI:

Image
Last edited by Timendus on Fri 26 Oct, 2007 1:54 pm, edited 1 time in total.
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

I'm not sure (without a debugger, and I'm not very good at running ASM in my head) but you could try writing $FF to the keypad to reset its group mask each iteration?

Putting in some delays wouldn't hurt for testing purposes (I had similar problems with my code, and throwing a few delays between port reads and writes cleaned them all up).

(The possessive form of "it" is "its", not "it's") ;)
User avatar
Jim e
Calc King
Posts: 2457
Joined: Sun 26 Dec, 2004 5:27 am
Location: SXIOPO = Infinite lives for both players
Contact:

Post by Jim e »

Those values suggest its returning the wrong group but the correct bit. Bits 3-5 of the return value are the group. Pindur shouldn't be responding like that, I'm guessing its because its the linux build and something old is left over.

For a while the key port was documented as being a masking value that needs to be reset before setting a new group, otherwise writing a new group to the port would AND on top of the current value. Thats not correct. Whatever byte is written to it is the new mask for group readings. So the reset by done by out (1),$FF is only needed when you are completely though using the key port and don't want to risk interference with other code.

Code: Select all

    ;; === keyboard_getkey ===
    ;;
    ;; Non-blocking getkey routine
    ;;
    ;; Post:
    ;;   a = key value

    keyboard_getkey:
        push hl
        push de
        push bc
        ld a,$ff
        out (KEYBOARD),a           ; reset keyport
        ld e,$fe                   ; frist group
        ld c,KEYBOARD              ; key port
        ld l,0                     ; l holds key pressed
    keyboard_getkey_loop:
        ld a,$FF
        out (KEYBOARD),a   ;This is all voodoo I assure you.
        nop
        nop

        out (c),e                  ; set keygroup
        ld b,8                     ; loop, Delay needed when work with key driver
        in a,(c)                   ; read key
    keyboard_getkey_bit:
        inc l                      ; inc to get key pressed
        rra                        ; if key pressed done
        jp nc,keyboard_getkey_done
        djnz keyboard_getkey_bit   ; loop 8
        rlc e                      ; next key group
        jp m,keyboard_getkey_loop  ; if bit 7 set loop
        ld l,0                     ; if no key pressed 0
    keyboard_getkey_done:
        ld a,l
        pop bc
        pop de
        pop hl
        ret
Image
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

Jim e wrote:Those values suggest its returning the wrong group but the correct bit. Bits 3-5 of the return value are the group. Pindur shouldn't be responding like that, I'm guessing its because its the linux build and something old is left over.
I see. I've tested it with pindurti under wine too, just to make sure, but it gave the same result. Your fix works, so I guess CoBB needs to fix that ;)
(The possessive form of "it" is "its", not "it's") ;)
Fixed, thanks!
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Jim e wrote:For a while the key port was documented as being a masking value that needs to be reset before setting a new group, otherwise writing a new group to the port would AND on top of the current value.
Hm, it still is documented as such on the WikiTI.
User avatar
Jim e
Calc King
Posts: 2457
Joined: Sun 26 Dec, 2004 5:27 am
Location: SXIOPO = Infinite lives for both players
Contact:

Post by Jim e »

Heh, well its on the talk page.
Image
User avatar
driesguldolf
Extreme Poster
Posts: 395
Joined: Thu 17 May, 2007 4:49 pm
Location: $4080
Contact:

Post by driesguldolf »

Ok, about time I get back on Vera :D (I've been busy with school ya know...)

I did it a bit different then you:
I have a routine that would return 2 values, in A the blocking key pressed and in D the non-blocking key (+ zflag according to A)
To simulate repeating keypresses from the arrow keys I have this little bit of code running in the interrupt:

Code: Select all

	; If no arrow key is pressed, reset the timer to 'longkeydelay'
	; Else decrement the timer,
	; If it hits zero clear (lastkey) and reset the timer to 'shortkeydelay'
	ld a, (lastkey)
	or a
	jr z, {+}
	cp 5
	; Only the arrow keys are allowed to repeat
	jr nc, {+}
keytimer	.equ $+1-interrupt_start+$8888
	ld a, 1
	dec a
	ld (keytimer), a
	jr nz, {++}
	; A is zero
	ld (lastkey), a
	ld a, (shortkeydelay)
	ld (keytimer), a
	jr {++}
+
	ld a, (longkeydelay)
	ld (keytimer), a
++
And (lastkey) being the key that was detected last time the getk routine ran
I know, I need to make this look better ;) (I wrote the code a while ago and it works so I'm satisfied :mrgreen:)

Hmmmm: ;)
Jim e wrote:

Code: Select all

        ld c,KEYBOARD              ; key port
        out (KEYBOARD),a   ;This is all voodoo I assure you.
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

I'm not sure this belongs on this forum, or in this thread... But what the heck :)

I don't really understand how your routine can be both blocking and non-blocking..? And you don't really do it differently, you have more features ;) My code doesn't do anything yet except returning a key value.

But adding repeating keys shouldn't need the interrupts, I think. I suppose we just need to add a simple timeout to this routine:

Code: Select all

;; === keyboard_waitkey ===
;; 
;; Blocking getkey routine, debounces, waits for one keypress
;; and returns it in a.
;;
;; Authors:
;;   Tim Franssen (mail@timendus.com)
;;
;; Post:
;;   a = value of key pressed

keyboard_waitkey:
	; Wait for previous keypress to get released
	call keyboard_waitup
keyboard_waitkey_loop:
	; Wait for keypress
	call keyboard_getkey
	or a
	jr z,keyboard_waitkey_loop
	ret
So that after pressing a key for a few tenths of a second it breaks out of the first waiting state.

(In all honesty, I don't really like this routine. Having to release all keys before you can press another makes it pretty difficult to type at a decent speed. But not waiting for it will give you all kinds of annoying echos. Either way, we need to work on this, and your input is very much appreciated :))
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
driesguldolf
Extreme Poster
Posts: 395
Joined: Thu 17 May, 2007 4:49 pm
Location: $4080
Contact:

Post by driesguldolf »

Timendus wrote:I'm not sure this belongs on this forum, or in this thread... But what the heck
Entirely correct :mrgreen:
It belongs in the Vera mailing group list whatever you call it :D
Post Reply