Lesson 11 : Evaluating user input
In this lesson, you will learn how to handle keypresses in ASM programs. In this lesson we will use two calls (GET_KEY and KEY_HAND) from the ROM and one call included in CrASH (CR_KHAND).
Key reading can also be done using ports, but that's for another lesson.
call GET_KEY |
ROM_CALL(KEY_HAND) |
call CR_KHAND |
example
call GET_KEY
This call gives you the scancode of the key that is currently pressed.
This scancode is stored in the A register. If there is no key pressed, A will be zero.
The scancodes for all the keys are stored in the keys.inc file, e.g. G_NONE is no key and G_ENTER is the scancode for the enter key.
To evaluate this output you will need to learn two new instructions: CP and SUB.
SUB m
This instruction subtracts the contents of a certain register from the A register.
The flags are set according to the answer.
The m can be A,B,C,D,E,H,L,(HL),(IX+n),(IY+n) or a data byte.
Some valid examples:
sub a ; a = a - a = 0
sub b ; a = a - b
sub (hl) ; a = a - (hl)
sub (IY+$05) ; a = a - (IY+$05)
sub 10 ; a = a - 10
|
CP m
This instructions is identical to the SUB instruction, but it does not store the result in the A register.
It does affect the flags, though.
This way, CP is the ideal register for comparing things.
Suppose we do CP 10, here's what the flags can tell us :
Flags for CP 10 |
Z |
C |
Conclusion |
1 (Z) |
0 (NC) |
A is equal to 10 |
0 (NZ) |
1 (C) |
A is smaller than 10 |
0 (NZ) |
0 (NC) |
A is bigger than 10 |
1 (Z) |
1 (C) |
Impossible |
What does this mean?
If the zero flag is set (Z), A is equal to 10.
If the zero flag is not set (NZ), A is not equal to 10.
If the carry flag is set (C), A is smaller than 10
if the carry flag is not set (NC), A is bigger than or equal to 10
Example
Below is a little example of how you can work with GET_KEY.
The routine will check if the ENTER or CLEAR key are pressed.
If this is the case, a jump is made to some labels elsewhere in the program.
If none of these keys is pressed, the program jumps back to the call GET_KEY line and checks the keys again.
WaitForKey:
call GET_KEY
cp G_ENTER
jr z,EnterPressed
cp G_CLEAR
jr z,ClearPressed
jr WaitForKey
|
ROM_CALL(KEY_HAND)
This call is somewhat different: when no key is pressed, the program does not continue, it just keeps waiting until a valid keypress is encountered.
KEY_HAND can also detect 2nd functions and alpha. It is also possible to change the contrast or to take screenshots with your linkcable in this loop.
A dissadvantage is that KEY_HAND also handles 2nd-off. This will turn off the calc. No problem so far.
But you might know that Ash relocates the program before it's started. This places the TI-OS in an unstable situation.
When a program finishes, Ash normally de-relocates the program so that everything is stable again.
When 2nd-off is pressed in a KEY_HAND call, the calc turns off and when it is turned back on, TI-OS is started with the calc still in the unstable state.
Guess what happens then... CRASH!
With KEY_HAND, the scancodes are different also. the K_XXX codes from keys.inc are used here.
Example
This example is basically the same as the one I gave with GET_KEY, but I made this one also detect the 2nd-mode keypress
and when another key was pressed, a jump is made to OtherKeyPressed.
ROM_CALL(KEY_HAND)
cp K_ENTER
jr z,EnterPressed
cp K_CLEAR
jr z,ClearPressed
cp K_QUIT
jr z,2nd_MODE_Pressed
jr OtherKeyPressed
|
call CR_KHAND
This is a call that is included ONLY in CrASH.
Programs that use this call can be compiled only for CrASH and will not run on Ash 3.0
The CR_KHAND call is almost identical to the ROM_CALL(KEY_HAND) call, but CrASH puts the RAM in a stable position before calling it.
This way, the calculator won't crash when it is turned off during this loop.
After the KEY_HAND romcall the program is relocated back to where it was when CR_KHAND was called and the program can continue.
One 'bad' thing with this routine is that CrASH will clear TEXT_MEM2, so you cannot have important information stored there when calling CR_KHAND.
Example
Once again the same example, but this time with CR_KHAND
call CR_KHAND
cp K_ENTER
jr z,EnterPressed
cp K_CLEAR
jr z,ClearPressed
cp K_QUIT
jr z,2nd_MODE_Pressed
jr OtherKeyPressed
|
Bigger Example
For your pleasure, here's a full program demonstrating the handling of keypresses, the CP instruction and conditional jumps.
.include "ti82.h" ; .include or #include, it's
#include "keys.inc" ; exactly the same
.org START_ADDR
.db "KeyPress Example",0
ROM_CALL(CLEARLCD)
ld a,'1' ; A contains ascii code for '1'
Loop:
ld hl,$0804 ; row 4 col 8
ld (CURSOR_POS),hl
ROM_CALL(TX_CHARPUT) ; write character in A to screen
ld b,a ; save contents of A somewhere
WaitForKey:
CALL GET_KEY
cp G_NONE
jr z,WaitForKey ; no key pressed? -> keep waiting
cp G_LEFT
jr z,LeftKeyPressed
cp G_RIGTH ; **
jr z,RightKeyPressed
cp G_CLEAR
ret z ; return when CLEAR key pressed
jr WaitForKey ; else, keep waiting for key
LeftKeyPressed:
ld a,b ; get contents of A back
dec a ; decrease contents of A
jr nz,Loop ; if not zero, it is OK
inc a ; if zero, put it back to one
jr Loop
RightKeyPressed:
ld a,b ; get contents of A back
inc a ; decrease contents of A
jr nz,Loop ; if not zero, it is OK
dec a ; if zero, put it back to $FF
jr Loop
.end
|
Note **: I know that G_RIGHT is not how it is supposed to be spelled, but it is also misspelled in the keys.inc file.
This example places a character in the middle of the screen.
When you start the program, the character is '1'.
You can change it with the left and right keys.
When the ascii code of the character is $01 or $FF, you can not change it to $00.
Exiting the program is done by pressing the clear key.
In this program, I also used conditions for the RET instruction. The ret instruction can take C,NC,Z,NZ,PO,PE,M and P as conditions.
New instructions
Here is a little table with all the new instructions from this lesson.
New instructions |
Mnemonic |
Operation |
SUB m |
Subtract from A, store answer in a
m can be A, B, C, D, E, H, L, (HL), (IX+n), (IY+n), N
|
CP m |
Compare A with m
m can be A, B, C, D, E, H, L, (HL), (IX+n), (IY+n), N
|
RET cc |
Return only if the condition is true
cc can be C, NC, Z, NZ, PO, PE, M or P
|
Previous lesson |
Contents |
Next lesson
|