News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Ast

PPI

Started by Ast, 19:59, 11 December 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ast

Hello,

I've just done a little proggy with keyboard tests (No firmware)
My problem is how can i do to delete keyboard repetition ?
For example, to see if it worked, i decided to test the right key.
In fact, when you press the right key, it increment A register 1 by 1. So the problem is :
First Key right pressed : A=1
Second Key right pressed : A=6
Third Key right pressed : A=16
...etc...
This is due to keyboard repetition and I've no idea about how to cancel that repetition. Who could help me ?

_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

TFM

What do you mean with repetition?
could you "just" set A back to 0?

TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Ast

yes i try to put set 1,a (after my test key) but it's not working... :-\
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

TFM

Can you place the source here?



TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Ast

Code is like that :


          ld d,0 ; keyboard line
          bit 1,a ; test bit 1-> Right Key
          jr nz,nextkey ; if a=1 go to next key
          set 1,a ; Put bit 1 to 1
          call rightkey  ; Rkey is pressed so goto RightKey proggy

nextkey

_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

Ast

Same times... We're always connected... :laugh:
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

arnoldemu

Remember old keyboard state.
Get new state.
Use xor to give changes.
Then check New is pressed or not as you need.

Keyboard repeat is made by firmware.
Hardware says if key pressed or not, but may be pressed for more than one frame.
So you need to manage it.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Ast

I Know that but my problem is how to do it? I've ever done many tests without any victory...  :'(
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

arnoldemu

#8
Quote from: Ast on 20:27, 11 December 14
I Know that but my problem is how to do it? I've ever done many tests without any victory...  :'(



loop:
ld b,&f5
l1:
in a,(c)
rra
jr nc,l1

;; wait until vsync is over
halt

halt

;; store current into old. it is from previous frame.
ld hl,cur_keyboard
ld de,old_keyboard
ld bc,10
ldir

;; read new keyboard state into cur_keyboard
call read_keyboard

ld a,(old_keyboard+9)
ld c,a
ld a,(cur_keyboard+9)
xor c
jr z,no_change

ld a,(cur_keyboard+9)
bit 1,a
jr z,no_press

;; press

no_press:

no_change:


jp loop






old_keyboard:
defs 10
cur_keyboard:
defs 10


a bit like that.

read_keyboard reads keyboard using ppi, it uses cpl, so that a key is pressed if bit value is 1.
Hardware normally returns bit value of 0 if key is pressed.

The above code remembers old. It does xor to know if there is a change. It then looks for a press.

So for the code to trigger, it sees the first time you press the key and will not repeat if you hold the key down.

EDIT: To work with release change this



ld a,(cur_keyboard+9)
bit 1,a
jr z,no_press


to


ld a,(cur_keyboard+9)
bit 1,a
jr nz,no_press


want to know if a key is held?


ld a,(old_keyboard+9)
ld c,a
ld a,(cur_keyboard+9)
and c
bit 1,a
jr nz,not_held

;; held


To be held, key must be pressed for 2 frames or more.


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Ast

I'm going to make a try, and I came back to tell you if it works... thanks.
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

TFM

Quote from: Ast on 20:09, 11 December 14
Code is like that :


          ld d,0 ; keyboard line
          bit 1,a ; test bit 1-> Right Key
          jr nz,nextkey ; if a=1 go to next key
          set 1,a ; Put bit 1 to 1
          call rightkey  ; Rkey is pressed so goto RightKey proggy

nextkey



Looks perfect to me!

TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Ast

So it works... Here comes the part of code I used (Hope it will help someone...who knows?)


main     ld b,#f5
           in a,(c)
           rra
           jr nc,main+2
;
           ld hl,oldstate
           ld de,currentstate
           ld bc,10                ; if you use all the keyboard lines
           ldir
;
Right
          ld d,0                   ; which line? d=Line 0
          call keyb               ; d=line / a=State (0=Nokey/1=KeyPressed)
          ld (oldstate+0),a    ; save OldState in line 0
          ld c,a                   ; save OldState in c
          ld a,(currentstate+0)
          xor c
          jr z,Left                 ; if a=0 then left Key
;
          ld a,c                    ; take old state
          bit 1,a                   ; Bit 1=Right Key
          jr nz,Left                ; if key isn't pressed go to the next keyboard test
;
          call Code_Right        ;  Execute Code_Right
;
Left     
          ld d,1                     ; line 1
          call keyb
          ld (oldstate+1),a      ; save oldstate in line 1
...etc...


Thanks to ArnoldEmu & TFM for Help !

May the Force be with U.


_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

Ast

Quote from: TFM on 21:30, 11 December 14

Looks perfect to me!

That's what i do first, but it doesn't work...
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

Rhino

A little idea for extended keyboard info:


    ;assuming that a = 1 if the fire key is pressed and 0 if not pressed

    rrca
    ld    a,(fireKeyCode)
    adc    a,a    ; a = a<<1 + c
    and    3     ; keep only bits 0 and 1
    ld    (fireKeyCode),a

    ; posible A values here

    ; 0 = no pressed
    ; 1 = just pressed
    ; 2 = just released
    ; 3 = keep pressed

    bit    0,a
    jr    nz/z, pressed / no_pressed

    cp    1
    jr    z, just_pressed

    cp    2
    jr    z, just_released

    cp    3
    jr    z, keep_pressing


Ast

why not ? another idea ?
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

arnoldemu

Quote from: Rhino on 23:18, 11 December 14
A little idea for extended keyboard info:


    ;assuming that a = 1 if the fire key is pressed and 0 if not pressed

    rrca
    ld    a,(fireKeyCode)
    adc    a,a    ; a = a<<1 + c
    and    3     ; keep only bits 0 and 1
    ld    (fireKeyCode),a

    ; posible A values here

    ; 0 = no pressed
    ; 1 = just pressed
    ; 2 = just released
    ; 3 = keep pressed

    bit    0,a
    jr    nz/z, pressed / no_pressed

    cp    1
    jr    z, just_pressed

    cp    2
    jr    z, just_released

    cp    3
    jr    z, keep_pressing



if you hold it for more than 3 it will wrap back to 0 and think you haven't pressed it?

better?

rrca
    ld    a,(fireKeyCode)
    adc    a,a    ; a = a<<1 + c
   cp 3
jr nz,ll1
ld a,3   
ll1:
ld    (fireKeyCode),a
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Quote from: arnoldemu on 10:02, 12 December 14
if you hold it for more than 3 it will wrap back to 0 and think you haven't pressed it?

better?

rrca
    ld    a,(fireKeyCode)
    adc    a,a    ; a = a<<1 + c
   cp 3
jr nz,ll1
ld a,3   
ll1:
ld    (fireKeyCode),a


EDIT: What happens if you release it?
firekeycode is not reset, so it doesn't see the press again?
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Rhino

Quote from: arnoldemu on 10:02, 12 December 14
if you hold it for more than 3 it will wrap back to 0 and think you haven't pressed it?

better?

rrca
    ld    a,(fireKeyCode)
    adc    a,a    ; a = a<<1 + c
   cp 3
jr nz,ll1
ld a,3   
ll1:
ld    (fireKeyCode),a


Hi,

The idea is that the bit 0 of the extended key status code is the current key state and bit 1 is the key state in the prev frame:

frame 1 -> key no pressed (0) -> extended key value = 0 (no pressed)
frame 2 -> key pressed (1) -> extended key value = 1 (just pressed)
frame 3 -> key pressed (1) -> extended key value = 3 (keep pressing)
frame 4 -> key pressed (1) -> extended key value = 3 (keep pressing)
frame 5 -> key no pressed (0) -> extended key value = 2 (just released)
frame 6 -> key no pressed (0) -> extended key value = 0 (no pressed)

In my example code, "and 3" avoid the problem you mean:

    ; a = 0 if fire is not pressed and 1 if pressed

    rrca            ; c = a
    ld    a,(fireKeyCode)
    adc    a,a    ; a = a<<1 + c
    and    3      ; keep only bits 0 and 1
    ld    (fireKeyCode),a   ; fireKeyCode possible values = 0,1,2 or 3

   




Rhino

Quote from: arnoldemu on 10:03, 12 December 14
EDIT: What happens if you release it?
firekeycode is not reset, so it doesn't see the press again?

While executing the code on each frame, the extended key status will be updated.
However, after a pause while loading or similar, you may want to put the extended key status to 0.

opqa

#19
There are several solutions to this "problem" depending on what you need.
This is the code I use in Yagol to scan the whole keyboard in a fast way. First I reserve some space in memory for two keyboard bitmaps.


align 32
.keybmapraw
ds 10,&ff
align 16
.keybmapfiltered
ds 10


The first one will store the raw keyboard bitmap, like reading the keyboard directly. The second one will store a filtered version that will use the xor technique described by arnoldemu to detect changes, whenever a key is first pressed, it will set the bit associated to that key. IIRC those two bitmaps are only updated every 8 frames in the current version of the program, enough for my needs. This is done during the interrupt path. The code that does it is the following:


; Scan keyboard
.scankeyb
ld bc,&f440
ld hl,keybmapraw

repeat 9

in a,(c)
ld d,a
xor (hl)
and (hl)
set 4,l
or (hl)
ld (hl),a
res 4,l
ld (hl),d
inc l

inc c
ld b,&f6
out (c),c
ld b,&f4

rend

in a,(c)
ld d,a
xor (hl)
and (hl)
set 4,l
or (hl)
ld (hl),a
res 4,l
ld (hl),d

ld bc,&f640
out (c),c
ret


This scans the whole keyboard, loops are unrolled for speed (note the use of "repeat" macro). I don't remember the whole details but also note that the PPI is already pre-initialized for keyboard scanning (the program doesn't use any sound so it's always in this state).

During the program, whenever I need to read the keyboard I just check those memory maps instead of directly reading the hardware. Also note that in the filtered keybmap, the same process that checks whether some key has been pressed has the responsibility to clear its corresponding bit when it has finished the action associated to it. Otherwise this bit will stay high forever no matter the key has already been released. These behaviour could be avoided within the scanning keyboard routine, but it would make it slower and as it is now it was OK for my needs.

EgoTrip

I was expecting this thread to be spam for some reason, for the PPI refunds.

sigh

Quote from: EgoTrip on 14:43, 03 January 15
I was expecting this thread to be spam for some reason, for the PPI refunds.

Exactly what I thought!

Powered by SMFPacks Menu Editor Mod