English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General > Coders. Tutorials

 
 
Thread Tools
Old 21 December 2011, 00:24   #1
jman
Registered User
 
Join Date: Nov 2010
Location: Italy
Posts: 307
[REQ:ASM] Reading a keystroke

Hello,

I'd like to read a keystroke, then based on what is pressed do <this> or <that>.
I'd like to do this in the most smooth way possible, thus using input.device

I've mumbled over the documentation and this post but I don't have clear what is needed to do. Basically I have to:
- CreateMsgPort()
- CreateIORequest()
- OpenDevice()
- SendIO() ? DoIO() ?

and then? Do I have to prepare an InputEvent struct?

Attached a tentative code snippet...

Thanks
Attached Files
File Type: s input.s (952 Bytes, 223 views)
jman is offline  
Old 21 December 2011, 22:02   #2
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,197
First, there are a few bugs in your code, f.ex you're doing "move.l name, a0" in a few places when you probably meant to do "lea name, a0" to get its address in memory, etc.

Do you want to wait until a keyboard event occurs, or do you want to check the current state of the keyboard? If you want to wait for an event then add an input handler through input.device using the IND_ADDHANDLER and IND_REMHANDLER commands and go through all incoming events. If you want to check the current state of the keyboard then send KBD_READMATRIX to keyboard.device instead. You can find thorough examples of this in the RKM Devices.
Leffmann is offline  
Old 21 December 2011, 23:29   #3
jman
Registered User
 
Join Date: Nov 2010
Location: Italy
Posts: 307
Yes, basically I want to have a "listener" and note down the keys that are sent.

I'll look further into it, thanks.
jman is offline  
Old 22 December 2011, 21:31   #4
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,197
Here's an example:

Code:
             include  exec/io.i
             include  exec/nodes.i
             include  exec/tasks.i
             include  exec/interrupts.i
             include  devices/input.i
             include  devices/inputevent.i

             macro    call
              xref    _LVO\1
              jsr     _LVO\1(a6)
             endm


             section  code

             move.l   4, a6
             call     CreateMsgPort
             move.l   d0, a5            ; a5 = MsgPort

             move.l   a5, a0
             move.l   #IOSTD_SIZE, d0
             call     CreateIORequest
             move.l   d0, a4            ; a4 = IOStdReq

             lea      inputdevice, a0
             moveq    #0, d0
             move.l   a4, a1
             clr.l    d1
             call     OpenDevice

             sub      #IS_SIZE, sp
             move.l   sp, a3            ; a3 = Interrupt

             ; set up our input handler

             sub.l    a1, a1
             call     FindTask
             move.l   d0, IS_DATA(a3)
             move.l   #handlercode, IS_CODE(a3)
             move.b   #127, LN+LN_PRI(a3)
             move.l   #handlername, LN+LN_NAME(a3)

             ; add it to the chain of handlers

             move.l   a3, IO_DATA(a4)
             move.w   #IND_ADDHANDLER, IO_COMMAND(a4)
             move.l   a4, a1
             call     DoIO

             ; put our task to sleep until we get the ABORT signal

             move.l   #SIGF_ABORT, d0
             call     Wait

             ; remove the handler and clean up

             move.l   a3, IO_DATA(a4)
             move.w   #IND_REMHANDLER, IO_COMMAND(a4)
             move.l   a4, a1
             call     DoIO

             add      #IS_SIZE, sp

             move.l   a4, a1
             call     CloseDevice
             move.l   a4, a0
             call     DeleteIORequest
             move.l   a5, a0
             call     DeleteMsgPort

             moveq    #0, d0
             rts



             ; the input handler receives a linked list of events in A0
             ; and must return the new list in D0. register A1 will
             ; contain the IS_DATA field of the Interrupt structure

handlercode  move.l   a0, d0

             ; check if we have pressed the escape key

.check       cmp.b    #IECLASS_RAWKEY, ie_Class(a0)
             bne      .next
             cmp.w    #69, ie_Code(a0)
             bne      .next

             ; null this event so they keypress isn't seen by the system

             move.b   #IECLASS_NULL, ie_Class(a0)

             ; signal ABORT to our task. (A1 already points to our task)

             movem.l  d0/a6, -(sp)
             move.l   4, a6
             move.l   #SIGF_ABORT, d0
             call     Signal
             movem.l  (sp)+, d0/a6
             rts

             ; check the next event in this list

.next        move.l    ie_NextEvent(a0), a0
             move.l    a0, d1
             bne       .check
             rts



handlername  dc.b      "test input handler", 0
inputdevice  dc.b      "input.device", 0
Leffmann is offline  
Old 23 December 2011, 00:13   #5
jman
Registered User
 
Join Date: Nov 2010
Location: Italy
Posts: 307
Uhm ... very interesting. Also, very clean and instructive code.

So, what I really need is a callback that handles the events and let me choose those interesting from those uninteresting.
With such a handler I can read all events passing through the device, correct?

Also, I think I see why I need such a listener: it wouldn't be possible to simply perfom a SendIO() with a CMD_READ set at IO_COMMAND offset of my IoStdReq. I would probably end up getting ... random data, I'd say, right? Not the input event I want, maybe I could intercept a mouse movement or whatever is passing through the input.device in that moment. right?

Maybe the CMD_READ is more targeted to reading from a serial interface?

Thanks for clarifying these points :-)
jman is offline  
Old 23 December 2011, 03:28   #6
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,197
Quote:
Originally Posted by jman View Post
So, what I really need is a callback that handles the events and let me choose those interesting from those uninteresting.
With such a handler I can read all events passing through the device, correct?
Yes all input events will pass through your handler.

Quote:
Originally Posted by jman
Also, I think I see why I need such a listener: it wouldn't be possible to simply perfom a SendIO() with a CMD_READ set at IO_COMMAND offset of my IoStdReq. I would probably end up getting ... random data, I'd say, right? Not the input event I want, maybe I could intercept a mouse movement or whatever is passing through the input.device in that moment. right?

Maybe the CMD_READ is more targeted to reading from a serial interface?

Thanks for clarifying these points :-)
CMD_READ is one of several commands that need to be supported by all devices, and a must for storage devices like trackdisk.device etc., but I don't think it has any effect when sent to input.device. It's not mentioned in the reference material for input.device at least.

There are other methods of getting input events and data from the keyboard that might be better depending on what kind of program you're writing, but this method works for everything and should handle external HIDs such as USB keyboards without any extra code.
Leffmann is offline  
Old 08 August 2012, 19:47   #7
Foul
Registered User

Foul's Avatar
 
Join Date: Jun 2009
Location: Perigueux/France
Age: 44
Posts: 1,325
Send a message via ICQ to Foul Send a message via MSN to Foul
Similar request :

i want, per exemple, when F1 is pressed to jump to a sub-routine.

is there simple way to do that ? i was thinking :

wait_F1:
cmp.b #$keycode,$bfec01
beq main

edit: just found by pure hazard F1 is $5F

None rawkey codes are corresponding : http://www.whdload.de/docs/en/rawkey.html


Last edited by Foul; 08 August 2012 at 23:22.
Foul is offline  
Old 09 August 2012, 01:22   #8
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,197
It's a bit more complicated than that. I've started writing a tutorial on the standard keyboard, joystick and mouse hardware, input routines are done but I need to write a demo program that puts it all together and shows how it works first. I'll try to finish it soon.
Leffmann is offline  
Old 09 August 2012, 01:31   #9
Foul
Registered User

Foul's Avatar
 
Join Date: Jun 2009
Location: Perigueux/France
Age: 44
Posts: 1,325
Send a message via ICQ to Foul Send a message via MSN to Foul
ok excellent

Nothing Hurry, i'm just learning some asm codes writting little progs for my own usage
Foul is offline  
Old 09 August 2012, 02:24   #10
Codetapper
2 contact me: email only!

Codetapper's Avatar
 
Join Date: May 2001
Location: Auckland / New Zealand
Posts: 3,150
Quote:
Originally Posted by Foul View Post
Similar request :

i want, per exemple, when F1 is pressed to jump to a sub-routine.

is there simple way to do that ? i was thinking :

wait_F1:
cmp.b #$keycode,$bfec01
beq main

edit: just found by pure hazard F1 is $5F

None rawkey codes are corresponding : http://www.whdload.de/docs/en/rawkey.html

The rawkey codes are different from the code returned from $bfec01. You need to do the following:

Code:
        move.b  $bfec01,d0      ;Get 'encoded' key that pressed
        ror.b   #1,d0
        not.b   d0
        move.b  d0,_KeyPressed  ;Store rawkey that was pressed

        cmp.b   #$50,d0	        ;Check for $50 = F1
        beq     _F1Pressed
        cmp.b   #$51,d0	        ;Check for $51 = F2
        beq     _F2Pressed
        ...
But it's a bit more complicated than that, as you have to acknowledge the keypress etc. There's a routine called _SetupKeyboard in keyboard.s in the WHDLoad development kit which has a complete keyboard routine in it. That'd be a good place to look, but it does hit the hardware rather than using intuition etc.
Codetapper is offline  
Old 09 August 2012, 09:26   #11
Foul
Registered User

Foul's Avatar
 
Join Date: Jun 2009
Location: Perigueux/France
Age: 44
Posts: 1,325
Send a message via ICQ to Foul Send a message via MSN to Foul
Good to know !
Foul is offline  
Old 24 July 2018, 12:47   #12
Yragael
Registered User

 
Join Date: Jun 2017
Location: Paris
Posts: 43
For those looking for a more hardware way, I just published two source codes for reading push / release of a key of the keyboard without using the system functions :

http://www.stashofcode.fr/routines-p...ker-sur-amiga/

First source code is for reading by polling, second source code is for reading by being interrupted. The key that is read is the ESC key.

(For those who downloaded the sources: I just cleaned the code, removing anything that was not useful)

Last edited by Yragael; 24 July 2018 at 13:12. Reason: Forgot to clean the code!
Yragael is offline  
Old 24 July 2018, 13:12   #13
phx
Natteravn

phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,225
Quote:
Originally Posted by Yragael View Post
First source code is for reading by polling, second source code is for reading by being interrupted. The key that is read is the ESC key.
Nice tutorial. Just two annotations:

- Why do you force the code into Chip RAM? When writing a demo or a game you always have too few Chip RAM, so you shouldn't put anything there which also works (better) in Fast RAM.

- Readability can be improved by limiting lines to 80 characters. I have seen some comment lines with a length of more than 20000 characters!
phx is offline  
Old 24 July 2018, 14:57   #14
Yragael
Registered User

 
Join Date: Jun 2017
Location: Paris
Posts: 43
Quote:
Originally Posted by phx View Post
Nice tutorial. Just two annotations:

- Why do you force the code into Chip RAM? When writing a demo or a game you always have too few Chip RAM, so you shouldn't put anything there which also works (better) in Fast RAM.

- Readability can be improved by limiting lines to 80 characters. I have seen some comment lines with a length of more than 20000 characters!
Yes, forcing the code in Chip is bad habit, and you are right to point it. I should have created a data section if data had to be loaded in Chip. Also, I will shorten the comments lines in new or updated tutorials for better readability (I'm writing code with Notepad++ on Windows and loading it in ASM-One from a directory mapped as a hard drive, and Notepad++ breaks line by itself, so I did not really noticed how annoying this can be).
Yragael is offline  
Old 22 September 2018, 15:02   #15
Steril707
OCS rocks!

 
Join Date: Sep 2016
Location: Amiga Island
Posts: 502
Who would have thought getting a keypress is more complicated than blitting on the Amiga...

Is there something less complicated than what we see above?

Coded a High Score List right now, and would like to implement some text input for the name now.
But it seems I will be going for entering your name with the Joystick. That stuff above would take me ages to get right in my code, I guess.
Steril707 is offline  
Old 22 September 2018, 15:15   #16
StingRay
move.l #$c0ff33,throat

StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,157
Quote:
Originally Posted by Steril707 View Post
Who would have thought getting a keypress is more complicated than blitting on the Amiga...

Is there something less complicated than what we see above?

Coded a High Score List right now, and would like to implement some text input for the name now.
But it seems I will be going for entering your name with the Joystick. That stuff above would take me ages to get right in my code, I guess.

It's not really that hard. Code a level 2 interrupt routine which handles the keys and simply use a mapping table to convert the rawkey codes to ascii characters.
StingRay is offline  
Old 22 September 2018, 16:14   #17
ross
Sum, ergo Cogito

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 48
Posts: 1,357
And also if you want to be system compliant, using input.device, is not so hard
ross is offline  
Old 22 September 2018, 16:41   #18
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 45
Posts: 3,328
And if you really want to be system compliant, open an intuition screen, a window on it, and use the IDCMP system
meynaf is offline  
Old 22 September 2018, 17:19   #19
phx
Natteravn

phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,225
Quote:
Originally Posted by Steril707 View Post
But it seems I will be going for entering your name with the Joystick. That stuff above would take me ages to get right in my code, I guess.
You may also look into input.asm from the Solid Gold source (should be the same in Trap Runner). It implements a Level 2 keyboard interupt handler and a FIFO queue for fast typing. Nevertheless it's quite compact.
phx is offline  
Old 22 September 2018, 18:55   #20
Photon
Moderator
Photon's Avatar
 
Join Date: Nov 2004
Location: Hult / Sweden
Posts: 4,591
#ChkKey.S here is a keyboard routine with a RawKey LUT, if it helps someone.

I'm not 100% sure this routine is compatible with A2000 keyboards made by Cherry (difference in behavior). All hardware routines should be checked on this combo(!)
Photon is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
[REQ:ASM] Sprite collisions basics jman Coders. Tutorials 5 03 September 2011 01:07
[REQ:ASM] Loading a static image and its palette jman Coders. Tutorials 3 04 June 2011 15:08
[REQ:ASM] Assembling and running jman Coders. Tutorials 9 07 May 2011 19:39
REQ:ASM getting elapsed time on A1200 jman Coders. Tutorials 18 11 January 2011 23:24
REQ:ASM How to use buffers jman Coders. Tutorials 7 01 December 2010 02:41

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 16:21.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.
Page generated in 0.09323 seconds with 14 queries