.module Key ; ========================================================================== ; GetState ; -------------------------------------------------------------------------- ; Gets the current state of a single key. ; -------------------------------------------------------------------------- ; Inputs: A - Scancode of the key to get the state of. ; Outputs: Carry - Reset if the key is pressed, set if released. ; Destroyed: AF, BC. ; ========================================================================== GetState: ; -------------------------------------------------------------------------- ; Scancodes are offset by one, so decrement and save in C. ; -------------------------------------------------------------------------- dec a ld c,a ; -------------------------------------------------------------------------- ; Reset the keypad hardware. ; -------------------------------------------------------------------------- ld a,$FF out (1),a ; -------------------------------------------------------------------------- ; The key mask is ~(1 << (scancode / 8)) ; -------------------------------------------------------------------------- ld a,c srl a srl a srl a ld b,a ld a,%11111110 jr z,+ -: rlca djnz - +: ; -------------------------------------------------------------------------- ; Output the key mask. ; -------------------------------------------------------------------------- out (1),a ; -------------------------------------------------------------------------- ; The index of the key in the retrieved bitmask is scancode & 7. ; -------------------------------------------------------------------------- ld a,c and 7 inc a ld b,a ; -------------------------------------------------------------------------- ; Read the keypad to fetch the input bitmask. ; -------------------------------------------------------------------------- in a,(1) ; -------------------------------------------------------------------------- ; Shift the desired bit out then return. ; -------------------------------------------------------------------------- -: srl a djnz - ret ; ========================================================================== ; GetCurrent ; -------------------------------------------------------------------------- ; Gets the currently pressed key's scancode. ; -------------------------------------------------------------------------- ; Outputs: A - Scancode of the pressed key, or 0 if no key is pressed. ; Z flag set if no key is pressed; reset if a key is pressed. ; Destroyed: AF, BC, DE, HL. ; ========================================================================== GetCurrent: ; -------------------------------------------------------------------------- ; D will count the current scancode (start from zero). ; E will store the current keypad mask. ; -------------------------------------------------------------------------- ld de,%01111111 ; -------------------------------------------------------------------------- ; H will store the pressed scancode when detected. ; L stores the counter for the number of keys pressed. It is started at ; two so that it can be decremented once and not set Z (to detect more than ; one pressed key) and will set Z when the routine ends (to indicate one key ; has been pressed). ; -------------------------------------------------------------------------- ld l,2 ; -------------------------------------------------------------------------- ; B stores the number of key groups to check (7). ; C stores 8 as a quick (and handy) constant. ; -------------------------------------------------------------------------- ld bc,7*256 + 8 ; -------------------------------------------------------------------------- ; Check each group in turn. ; -------------------------------------------------------------------------- GroupCheckLoop: push bc ; -------------------------------------------------------------------------- ; Reset the keypad hardware. ; -------------------------------------------------------------------------- ld a,$FF out (1),a ; -------------------------------------------------------------------------- ; Advance to then select the next group. ; -------------------------------------------------------------------------- rlc e ld a,e out (1),a ; -------------------------------------------------------------------------- ; We have eight bits to check. ; -------------------------------------------------------------------------- ld b,c nop ; -------------------------------------------------------------------------- ; Sample the keypad. Have any keys been pressed? ; -------------------------------------------------------------------------- in a,(1) cpl jr z,NoKeyInMask ; -------------------------------------------------------------------------- ; Check each bit in turn. ; -------------------------------------------------------------------------- -: inc d srl a jr nc,+ ; -------------------------------------------------------------------------- ; A key has been pressed. Has one already been pressed? ; -------------------------------------------------------------------------- dec l jr z,NotOneKeyPressed ; -------------------------------------------------------------------------- ; Store the pressed key value. ; -------------------------------------------------------------------------- ld h,d ; -------------------------------------------------------------------------- ; Advance to the next bit. ; -------------------------------------------------------------------------- +: djnz - jr CheckNextGroup ; -------------------------------------------------------------------------- ; No key has been pressed in the group, so speed ahead to the next one. ; -------------------------------------------------------------------------- NoKeyInMask: ld a,d add a,c ld d,a ; -------------------------------------------------------------------------- ; Do we have more groups to check? ; -------------------------------------------------------------------------- CheckNextGroup: pop bc djnz GroupCheckLoop ; -------------------------------------------------------------------------- ; Was exactly one key pressed? ; -------------------------------------------------------------------------- dec l jr z,+ ; -------------------------------------------------------------------------- ; Not exactly one key was pressed, so clear. ; -------------------------------------------------------------------------- xor a ret ; -------------------------------------------------------------------------- ; Exactly one key was pressed! ; -------------------------------------------------------------------------- +: ld a,h or a ret ; -------------------------------------------------------------------------- ; If more than one key is pressed, bail out of the main loop here. ; -------------------------------------------------------------------------- NotOneKeyPressed: pop bc xor a ret ; ========================================================================== ; GetOneShot ; -------------------------------------------------------------------------- ; Get the currently pressed key, but only report its scancode if it was ; not previously pressed. This will only return the scancode once. ; -------------------------------------------------------------------------- ; Outputs: A - Scancode of the pressed key, or 0 if no key is pressed. ; Z flag set if no key is pressed; reset if a key is pressed. ; Destroyed: AF, BC, DE, HL. ; ========================================================================== GetOneShot: ; -------------------------------------------------------------------------- ; Get the current key. ; -------------------------------------------------------------------------- call GetCurrent jr nz,+ ; -------------------------------------------------------------------------- ; No key is pressed - record that. ; -------------------------------------------------------------------------- ld (PreviousScancode),a ret ; -------------------------------------------------------------------------- ; Is it the same key as last time? ; -------------------------------------------------------------------------- +: ld b,a ld a,(PreviousScancode) cp b jr nz,+ ; -------------------------------------------------------------------------- ; It's the same key. ; -------------------------------------------------------------------------- xor a ret ; -------------------------------------------------------------------------- ; It's a different key! Record it then return it. ; -------------------------------------------------------------------------- +: ld a,b ld (PreviousScancode),a ret .endmodule