The Spectrum keyboard can be read from the following Z80 ports:
Bits are set to 0 for any key that is pressed and 1 for any key that is not pressed. Multiple key presses can be read simultaneously.
To read the QWERT row and test for Q, you could do something like this:
LD BC,&FBFE ; Load BC with the row port address IN A,(C) ; Read the port into the accumulator AND %00000001 ; Mask out the key we are interested in JR Z,Q_KEY_PRESSED ; If the result is zero, then the key has been pressed...
So, going on from that, here is a keyboard read routine that will return a keypress. It doesn’t do anything clever and will return the first key found if multiple keys are pressed, but it’s a start and probably good enough for front end pages, and so on…
Read_Keyboard: LD HL,Keyboard_Map ; Point HL at the keyboard list LD D,8 ; This is the number of ports (rows) to check LD C,&FE ; C is always FEh for reading keyboard ports Read_Keyboard_0: LD B,(HL) ; Get the keyboard port address from table INC HL ; Increment to list of keys IN A,(C) ; Read the row of keys in AND &1F ; We are only interested in the first five bits LD E,5 ; This is the number of keys in the row Read_Keyboard_1: SRL A ; Shift A right; bit 0 sets carry bit JR NC,Read_Keyboard_2 ; If the bit is 0, we've found our key INC HL ; Go to next table address DEC E ; Decrement key loop counter JR NZ,Read_Keyboard_1 ; Loop around until this row finished DEC D ; Decrement row loop counter JR NZ,Read_Keyboard_0 ; Loop around until we are done AND A ; Clear A (no key found) RET Read_Keyboard_2: LD A,(HL) ; We've found a key at this point; fetch the character code! RET Keyboard_Map: DB &FE,"#","Z","X","C","V" DB &FD,"A","S","D","F","G" DB &FB,"Q","W","E","R","T" DB &F7,"1","2","3","4","5" DB &EF,"0","9","8","7","6" DB &DF,"P","O","I","U","Y" DB &BF,"#","L","K","J","H" DB &7F," ","#","M","N","B"