;PC Keyboard routines - Communications section ;--------------------------------------------- ;(c) 1995 Simon Cooke pckey: EQU 232 ;pc keyboard port inhibit: EQU datahigh ;clock low, data high enable: EQU 3 datahigh: EQU 1 clockhigh: EQU 2 baderror: EQU 16 ;after 16 errors, die horribly ;with knives in its orifices. ;Comms routines ;============== ;Wait until keyboard lines are both unasserted ;--------------------------------------------- wait.ready: IN A,(pckey) CPL AND 3 RET Z JR wait.ready ;Prevent the keyboard from sending ;--------------------------------- ;(drop clock line low, keep data line high) inhibit.keybd: LD A,inhibit OUT (pckey),A RET ;Send command ;------------ ;Entered with command in A send.command: LD (command),A resendcommand: LD A,(command) CALL send.byte waitresponse: CALL read.byte CP resend JR Z,resendcommand CP ack JR NZ,waitresponse RET ;Allow the keyboard to txmit ;--------------------------- ;Set both clock & data lines high ;(Use for stop bits as well) enable.keybd: send.stopbit: LD A,enable OUT (pckey),A RET ;Read a byte from the keyboard... ;-------------------------------- ;Returns with byte in the A register read.byte: XOR A LD (error),A dontblitzerrr: CALL enable.keybd CALL wait.ready LD HL,keybuff LD B,11 wforlow: CALL waitclklow ;data bit is now in bit 0 ofA LD (HL),A INC HL CALL waitclkhigh DJNZ wforlow CALL inhibit.keybd LD HL,keybuff+1 LD B,8 inloop: RR (HL) RRA INC HL DJNZ inloop LD C,A AND A LD A,(HL) JP PO,testeven RRA JR C,okaypt parityerror: LD A,(error) INC A LD (error),A CP baderror JP Z,badcrash LD C,&FE ; resend command CALL dontblitzerrs ;send, keeping error status JR dontblitzerrr ;read, keeping error status testeven: RRA JR C,parityerror okaypt: LD A,C RET ;Send a byte to the keyboard... ;------------------------------ ;Enter with byte in A register. send.byte: LD C,A XOR A LD (error),A dontblitzerrs: CALL enable.keybd ;Convert character & stick it in the buffer. LD HL,keybuff LD B,8 sendl: LD A,1 RRC C RLA LD (HL),A INC HL DJNZ sendl LD A,C AND A JP PO,parityodds parityevens: LD (HL),enable ;clock set high, data high ;(parity bit) JR parityends parityodds: LD (HL),clockhigh ;clock set high, data low ;(parity bit) parityends: LD HL,keybuff CALL wait.ready CALL inhibit.keybd XOR A ;tell it we want to start OUT (pckey),A ;sending - clock & data low CALL delay LD A,clockhigh ;keep data low, give keyboard ;the clock line to play with OUT (pckey),A LD HL,keybuff LD B,9 keysendl: CALL waitclklow LD A,(HL) OUT (pckey),A CALL waitclkhigh INC HL DJNZ keysendl ;do rest of bits ;Send stop bit - both lines high our end. CALL waitclklow CALL send.stopbit ;end of data byte - keyboard drives both lines low. We must ;check for this to ensure that the byte has been received. ;It also allows us to then inhibit the keyboard. wait.blow: IN A,(pckey) AND 3 JR NZ,wait.blow CALL inhibit.keybd RET ;Wait for clock line to go low ;----------------------------- waitclklow: IN A,(pckey) ;wait for clock to go low BIT 1,A JR NZ,waitclklow RET ;Wait for clock line to go high ;------------------------------ waitclkhigh: ;wait for clock to go high IN A,(pckey) BIT 1,A JR Z,waitclkhigh RET delay: PUSH BC LD B,5 DJNZ $ POP BC RET keybuff: DEFS 11 ;serial encoding/decoding buffer error: DEFB 0 command: DEFB 0